import * as d3 from "./d3.v5.js";
// import * as const_data from "./const.js";
// import { tickStep } from "d3";

var _self = {
  transScale: {
    transX: 0,
    transY: 0,
    scale: 0,
    transYRatio: -100
  },
  markup_groups: {},
  markup_groups_bottom: {}
};

_self.zoom = d3
  .zoom() //定义缩放方法
  .duration(750)
  .on("zoom", function () {
    // zoom事件
    _self.circles_group.attr(
      "transform",
      d3.zoomTransform(_self.svg.node()) + " scale(1,-1)"
    ); //缩放平移都是在操作g元素  + " rotate(0)"
  });

// var circles_group;
function AddSvg(filePath, divId, mouseCallBack) {
  var f = document.getElementById(divId);
  var childs = f.childNodes;
  for (var i = 0; i < childs.length; i++) {
    f.removeChild(childs[i]);
  }
  g_markupList = [];

  var tar = document.getElementById(divId);

  tar.innerHTML = "";
  // var cssstyle = "html, body {height: 100%;}";
  // cssstyle += "html, body, div, svg {margin: 0;padding: 0;}";
  // cssstyle += ".red {fill: #FF0000;stroke: #FF0000;}";
  // cssstyle += ".green {fill: #00ff00;stroke: #00ff00;}";
  // cssstyle += ".blue {fill: #0000ff;stroke: #0000ff;}";
  // cssstyle +=
  //   "#" +
  //   divId +
  //   "{ overflow:hidden;width:100%; height:100%;margin:auto 0 }";
  d3.select(tar)
    .append("style")
    // .html(cssstyle)
    ;

  //屏蔽右键
  // tar.oncontextmenu = function () {
  //   // event.returnValue = false;
  // };

  d3.svg(filePath).then(function (data) {
    var test = data.getElementsByTagName("svg"); //取出画布中的内容
    _self.svg = d3
      .select("#" + tar.id)
      .append("svg")
      .attr("id", "svg" + tar.id); //创建画布

    var docdata = test["0"].innerHTML;
    var defs = _self.svg.append("defs");
    var catpattern = defs.append("pattern")
      .attr("id", "catpattern_cloud")
      .attr("x", 100)
      .attr("y", 100)
      .attr("height", 1)
      .attr("width", 1)
      .attr("patternUnits", "objextBoundingBox");// userSpaceOnUse objextBoundingBox

    catpattern.append("circle")
      .attr("cx", 10)
      .attr("cy", 10)
      .attr("r", 5)
      .attr("fill", "red");

    catpattern.append("polygon")
      .attr("points", "30 10 60 50 0 50")
      .attr("fill", "green");

    _self.circles_group = _self.svg.append("g").attr("id", "g" + tar.id); //创建一个g元素用来包裹svg文件去掉画布标签的其他标签内容
    _self.circles_group.html(docdata);

    var padding = 0; //边距
    var clientHeight = tar.offsetHeight - padding; //  window.innerHeight - padding;
    var clientWidth = tar.offsetWidth - padding; //document.body.offsetWidth - padding; //window.innerWidth;

    _self.svg
      .attr("preserveAspectRatio", "xMinYMin meet")
      .attr("width", clientWidth)
      .attr("hieght", clientHeight)
      .attr("rotate", 180)
      .attr("viewBox", "0 0 " + clientWidth + " " + clientHeight + ""); //这里是容器的宽高

    var boundbox = _self.circles_group.node().getBoundingClientRect();
    boundbox.x = boundbox.x + 0;
    boundbox.y = boundbox.y - 75;


    var svgheight = boundbox.height;
    var svgwidth = boundbox.width;
    g_editDotWidth = Math.min(svgwidth / 500, svgheight / 500);

    var ScalingRatio = 0.9 * Math.min(
      clientHeight / svgheight,
      clientWidth / svgwidth
    );
    g_markupLineWidth = Math.min(svgwidth, svgheight) / 1500;

    var scalex = (0 - boundbox.x + 42) * ScalingRatio;
    scalex += (clientWidth - boundbox.width * ScalingRatio) / 2;

    // var scaley = (boundbox.y + svgheight) * ScalingRatio_count;
    // scaley += _self.transScale.transYRatio;

    // var scaley = (clientHeight) * 0.95;
    // scaley += boundbox.y * ScalingRatio;

    // if(clientHeight > clientWidth) {
    //   scaley = (0 - boundbox.y + 50) * ScalingRatio;
    //   scaley += (clientHeight - boundbox.height / ScalingRatio);  
    // }

    var scaley = (0 + boundbox.y) * ScalingRatio;
    scaley += clientHeight - (clientHeight - boundbox.height * ScalingRatio) / 2;



    // scaley += 20;

    _self.transScale.transX = scalex;
    _self.transScale.transY = scaley;
    _self.transScale.scale = ScalingRatio;

    var zoomOnce = d3
      .zoom() //定义缩放方法
      .duration(750)
      .on("zoom", function () {
        // zoom事件
        // var eventIn = d3.event;
        // var sourceEvent = eventIn.sourceEvent;
        // if (sourceEvent != null) {
        //   var sourceEventType = sourceEvent.type;
        //   var wheelDelta = sourceEvent.wheelDelta;

        //   var transformStr = _self.circles_group.attr("transform");
        //   console.log(transformStr)
        //   var scaleRate = 0;
        //   if (transformStr) {
        //     var transformStrSplits = transformStr.split(") scale(")
        //     console.log(transformStrSplits)
        //     scaleRate = transformStrSplits[1];
        //   }

        //   if (wheelDelta < 0 && Number(scaleRate) < _self.transScale.scale / 3) {
        //     // d3.event.sourceEvent.wheelDelta = 0;

        //     d3.setScaleEnble(false);
        //     event.stopPropagation();//阻止事件冒泡
        //     event.preventDefault();  //阻止默认行为
        //     return null;

        //   }
        //   if (wheelDelta > 0 && Number(scaleRate) > _self.transScale.scale * 3) {
        //     // d3.event.sourceEvent.wheelDelta = 0;
        //     d3.setScaleEnble(false);

        //     event.stopPropagation();//阻止事件冒泡
        //     event.preventDefault();  //阻止默认行为
        //     return null;
        //   }
        // }

        // d3.setScaleEnble(true);

        _self.circles_group.attr(
          "transform",
          d3.zoomTransform(_self.svg.node()) + " scale(1,-1)"
        ); //缩放平移都是在操作g元素  + " rotate(0)"
      });

    _self.svg
      .call(zoomOnce)
      .call(
        zoomOnce.transform,
        d3.zoomIdentity.translate(scalex, scaley).scale(ScalingRatio)
      );
    d3.SetInitScale(_self.transScale.scale);

    //   背景框  用于鼠标位置检测


    // var svgroot = svg.append("g").attr("id", "svgroot");//创建一个g元素用来包裹svg文件去掉画布标签的其他标签内容

    // end
    _self.circles_group.on("mousemove", function () {
      // 添加交互内容
      var x = d3.mouse(this)[0];
      var y = d3.mouse(this)[1];

      if (mouseCallBack != null) {
        mouseCallBack(x, y);
      }
      _self.mousePosX = x;
      _self.mousePosY = y;

      if (g_SelectedMarkup) {
        g_SelectedMarkup.onBoundBoxDotMouseMove(g_dotIndex);
        g_SelectedMarkup.onBoundBoxShapeMouseMove(g_dotIndex);
      }

      if (g_state == OPT_STATE.STATE_ADDING && g_SelectedMarkup != null) {
        g_SelectedMarkup.updateLastPosition({ x: x, y: y }, false);
      }
    });


    // 鼠标右键
    _self.circles_group.on("contextmenu", function (d, i) {

      // d3.event.preventDefault();

      event.returnValue = false;

      //右键单击
      var x = d3.mouse(this)[0];
      var y = d3.mouse(this)[1];
      var but = d3.event.button;
      console.log("but = " + but)

      if (g_state == OPT_STATE.STATE_ADDING && g_SelectedMarkup != null) {
        g_SelectedMarkup.updateLastPosition({ x: x, y: y }, true);

        if (g_SelectedMarkup.typeId == 11) {
          g_openTextInputFun(g_SelectedMarkup.originData.text);

        } else {
          changeGlobalState(3, g_createShapeTypeId);
        }

        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      }

    });

    // 鼠标左键
    _self.circles_group.on("mouseup", function () {
      console.log("mouseup")
      // 添加交互内容
      var x = d3.mouse(this)[0];
      var y = d3.mouse(this)[1];

      var but = d3.event.button;
      console.log("but = " + but)

      if (but != 0)
        return;

      var _changeToAdd = false;
      if (g_state == OPT_STATE.STATE_ADDING && g_SelectedMarkup == null) {
        g_SelectedMarkup = addMarkUpByParams(g_createShapeTypeId, g_params, { x: x, y: y });
      } else if (g_state == OPT_STATE.STATE_ADDING && g_SelectedMarkup != null) {
        _changeToAdd = addMarkUpPosition(g_createShapeTypeId, g_params, { x: x, y: y });
      }
      else if (g_state == OPT_STATE.STATE_CHANGING) {
        // var dataindex = d3.select(this).attr("dataIndex");
        g_SelectedMarkup.onBoundBoxDotMouseUp(g_dotIndex);
        g_dotIndex = -1;
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      }

      if (_changeToAdd) {
        g_SelectedMarkup.updateLastPosition({ x: x, y: y }, true);
        changeGlobalState(3, g_createShapeTypeId);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      }
    });

    window.onresize = function () {
      console.log("window.onresize");

      var padding = 0; //边距
      var clientHeight = tar.offsetHeight - padding; //  window.innerHeight - padding;
      var clientWidth = tar.offsetWidth - padding; //document.body.offsetWidth - padding; //window.innerWidth;

      _self.svg
        .attr("preserveAspectRatio", "xMinYMin meet")
        .attr("width", clientWidth)
        .attr("hieght", clientHeight)
        // .attr("rotate", 180)
        .attr("viewBox", "0 0 " + clientWidth + " " + clientHeight + ""); //这里是容器的宽高
    };

    var boxX = test[0].viewBox.baseVal.x;
    var boxY = test[0].viewBox.baseVal.y;
    var boxWidth = test[0].viewBox.baseVal.width;
    var boxHeight = test[0].viewBox.baseVal.height;
    initMarkupLayer(boxX, boxY, boxWidth, boxHeight);

    if (g_loadCallback)
      g_loadCallback();
  });
}

function ResetSvgView() {
  _self.svg.call(
    _self.zoom.transform,
    d3.zoomIdentity
      .translate(_self.transScale.transX, _self.transScale.transY)
      .scale(_self.transScale.scale)
  );
  d3.SetInitScale(_self.transScale.scale);
}

/**
 * 设置鼠标操作类型  1 缩放  2 移动
 * @param {*} index mode  index
 */
function SetSvgMouseMode(index) {
  d3.SetMouseMode(index);
}

function GetMousePositonOnSvgX() {
  return _self.mousePosX;
}

function GetMousePositonOnSvgY() {
  return _self.mousePosY;
}

function AddSimpleMarkup(markX, markY) {
  var x = parseFloat(markX);
  var y = parseFloat(markY);

  _self.circles_group.append("circle")
    .attr("r", "20")
    .attr("cx", x)
    .attr("cy", y)
    .attr("fill", "red");//创建一个g元素用来包裹svg文件去掉画布标签的其他标签内容

}

function initMarkupLayer(boxX, boxY, boxWidth, boxHeight) {

  _self.markup_groups_bottom = _self.circles_group.insert("g", "clipId0").attr("id", "g-markups-bottom"); //创建一个g元素用来包裹svg文件去掉画布标签的其他标签内容
  _self.markup_groups_bottom.each(function () {
    this.parentNode.insertBefore(this, this.parentNode.firstChild);
  });


  var backgroundBox = _self.circles_group
    .insert("rect", "g-markups-bottom")
    .attr("id", "backRect");
  backgroundBox.attr("style", "fill:rgba(0,0,255,0)");
  backgroundBox.attr("fill", "rgba(0,0,255,0)");

  backgroundBox.attr("x", boxX - boxWidth);
  backgroundBox.attr("y", boxY - boxHeight);
  backgroundBox.attr("width", 3 * boxWidth);
  backgroundBox.attr("height", 3 * boxHeight);

  backgroundBox.each(function () {
    this.parentNode.insertBefore(this, this.parentNode.firstChild);
  });
  // markup_group
  _self.markup_groups = _self.circles_group.append("g").attr("id", "g-markups"); //创建一个g元素用来包裹svg文件去掉画布标签的其他标签内容

}

var LINE_STROKE_DASH_TYPE = [
  "0",
  "5,5",
  "10,10",
  "20,10,20,10",
  "20,5,10,5",
];

var OPT_STATE = {
  STATE_NORMAL: 0,
  STATE_CHANGING: 1,
  STATE_MOVING: 2,
  STATE_ADDING: 3,
};

var g_SelectedMarkup = null;
var g_editDotWidth = 1; // 包围盒黑点宽度
var g_editDotStroke = "#000000"; // 包围盒黑点宽度
var g_editDotFill = "#000000"; // 包围盒黑点宽度
var g_moveLastPos = { x: 0, y: 0 }; // 用于移动  标记上一次位置
var g_params = {};
var g_createShapeTypeId = -1;
var g_selectedCallBackFun;
var g_openTextInputFun;
var g_loadCallback;
var g_updateMarkupBaseInfoFun;

var g_markupLineWidth = 1;

var g_state = OPT_STATE.STATE_NORMAL;
var g_dotIndex = -1; // 点击的包围盒点的index  用于确定跟随鼠标移动的动作类型
var g_markupList = []; // 所有markup对象


function setGParams(e) {
  g_params = e;
  if (g_SelectedMarkup != null) {
    g_SelectedMarkup.updateParams(g_params);

    if (g_state == OPT_STATE.STATE_ADDING && (g_createShapeTypeId == 10 || g_createShapeTypeId == 11)) {
      changeGlobalState(3, g_createShapeTypeId);
      event.stopPropagation();//阻止事件冒泡
      event.preventDefault();  //阻止默认行为
    }
  }
}

/**
 * e 0 mormal  3 adding
 * @param {*} shapeTypeId 图形id
 * @param {*} params 参数 
 */
function changeGlobalState(stateid, shapeTypeId) {
  var oldState = g_state;
  g_createShapeTypeId = shapeTypeId;
  if (stateid == 0) {
    g_state = OPT_STATE.STATE_NORMAL;
  }
  else if (stateid == 3) {
    g_state = OPT_STATE.STATE_ADDING;
    if (g_SelectedMarkup != null)
      g_SelectedMarkup.setSelected(false);
    g_SelectedMarkup = null;
  }
}

function setLoadCallBack(inCallBack) {
  g_loadCallback = inCallBack;
}

function setSelectCallBack(inCallBack) {
  g_selectedCallBackFun = inCallBack;
}

function setOpenInputTextCallBack(inCallBack) {
  g_openTextInputFun = inCallBack;
}



/**
 * MarkupBase  Markup 
 * @param {*} originData  外部传入的原始数据
 * @param {*} inTypeId 图形类型
 */
function MarkupBase(originData, inTypeId) {
  this.originData = originData;

  /**
   * box 0 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   */
  this.boundboxDots = [];
  this.typeId = inTypeId;
  var _MarkupBaseSelf = this;
  this.boundBoxShap = null; // 包围盒子
  this.contentShap = null;
  this.contentShapBottom = null;

  this.dotInfoList = []; // 包围盒 黑点

  this.addGroups = function () {
    this.rootGroup = _self.markup_groups.append("g").attr("id", "g-markup" + this.typeName); // 标记根节点
    this.contentGroupBottom = _self.markup_groups_bottom.append("g").attr("id", "g-markup-bottom" + this.typeName); // 标记根节点

    this.contentGroup = this.rootGroup.append("g").attr("id", "g-content"); // 标记shap g
    this.boundboxGroup = this.rootGroup.append("g").attr("id", "g-boundbox"); // 标记包围g
  };

  /**
   * 内容的公共数据参数
   */
  this.apandBaseInfo = function () {
    var nRGBLColor = this.originData.selectedLineColor;// 线色
    var nRGBFillColor = this.originData.selectedFillColor;// 填充颜色
    var sFillType = this.originData.selectedFillType;// 填充类型 1 填充 2 填充  置于底层
    var sLineStyle = this.originData.selectedLineType;// 线型
    var wLineThick = this.originData.selectedLineWidth;// 线宽

    if (nRGBLColor) {
      this.contentShap.attr("stroke", nRGBLColor);
    }

    if (wLineThick) {
      this.contentShap.attr("stroke-width", g_markupLineWidth * wLineThick / 2);
    }

    // fill
    {
      var fillcolor = nRGBFillColor;
      this.contentShap.attr("fill", sFillType == 1 ? fillcolor : "#00000000");
      if (this.contentShapBottom != null)
        this.contentShapBottom.attr("fill", sFillType == 2 ? fillcolor : "#00000000");
    }

    if (sLineStyle != null) {
      this.contentShap.attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[sLineStyle]);
    }
  };

  this.addGroups();
  this.addBoundBoxContents();
  this.addContents();

  this.setSelected = function (isS) {
    g_SelectedMarkup = this;
    this.isSelected = isS;
    // this.boundBoxShap.attr("stroke", isS ? "#00000033" : "#00000000")
    this.boundboxGroup.attr("visibility", isS ? "visible" : "hidden");

    if (isS)
      g_selectedCallBackFun(g_SelectedMarkup.originData);
  };

  this.onShapeClick = function () {
    if (g_state == OPT_STATE.STATE_NORMAL) {
      if (!_MarkupBaseSelf.isSelected) {
        if (g_SelectedMarkup != null)
          g_SelectedMarkup.setSelected(false);
        _MarkupBaseSelf.setSelected(true);
        g_SelectedMarkup = _MarkupBaseSelf;
      }
    }
  };

  /**
   * 包围黑点 按下 
   * @param {*} index dot index 
   * @param {*} optType dot 类型  
   */
  this.onBoundBoxDotMouseDown = function (index) {
    if (g_state == OPT_STATE.STATE_NORMAL) {
      console.log("onBoundBoxDotMouseDown index = " + index);
      g_state = OPT_STATE.STATE_CHANGING;
      g_dotIndex = index;
    }
  }

  /**
   * 
   * @param {*} index dot index 
   * @param {*} optType dot 类型
   */
  this.onBoundBoxDotMouseUp = function (index) {
    console.log("onBoundBoxDotMouseUp index = " + index);
    g_state = OPT_STATE.STATE_NORMAL;
    g_dotIndex = -1;
  }

  /**
   * change状态下移动鼠标
   * @param {*} index dot index 
   * @param {*} optType dot 类型
   */
  this.onBoundBoxDotMouseMove = function (index) {
    if (g_state != OPT_STATE.STATE_CHANGING)
      return;

    var mouseosX = GetMousePositonOnSvgX();
    var mouseosY = GetMousePositonOnSvgY();

    // 更新
    this.updateDrawShape(index, mouseosX, mouseosY);
  };

  this.onBoundBoxShapeMouseDown = function (index) {
    // 开始移动位置
    if (g_state == OPT_STATE.STATE_NORMAL && this.isSelected) {
      g_state = OPT_STATE.STATE_MOVING;
      g_moveLastPos.x = GetMousePositonOnSvgX();
      g_moveLastPos.y = GetMousePositonOnSvgY();
    }
  }

  this.onBoundBoxShapeMouseUp = function (index) {
    // 移动结束
    if (g_state == OPT_STATE.STATE_MOVING && this.isSelected) {
      g_state = OPT_STATE.STATE_NORMAL;
    }
  }

  this.onBoundBoxShapeMouseMove = function (index) {
    if (g_state != OPT_STATE.STATE_MOVING)
      return;
    // 移动位置
    var dx = GetMousePositonOnSvgX() - g_moveLastPos.x;
    var dy = GetMousePositonOnSvgY() - g_moveLastPos.y;
    this.updateDrawPosition(dx, dy);
    g_moveLastPos.x = GetMousePositonOnSvgX();
    g_moveLastPos.y = GetMousePositonOnSvgY();
  };

  this.updateDrawPosition = function (dx, dy) {
    for (var i = 0; i < this.originData.pointList.length; i++) {
      this.originData.pointList[i].x = Number(this.originData.pointList[i].x) + dx;
      this.originData.pointList[i].y = Number(this.originData.pointList[i].y) + dy;
      this.addContents();
      this.addBoundBoxContents();
    }
  };

  /**
   * 更新最后一个点的位置  矩形图形 重置左下点和右上点
   * @param {*} inPos 
   * @param {*} isEnd 
   */
  this.updateLastPosition = function (inPos, isEnd) {
    if (this.typeId != 8) {
      this.originData.pointList[this.originData.pointList.length - 1].x = inPos.x;
      this.originData.pointList[this.originData.pointList.length - 1].y = inPos.y;
    } else {
      this.originData.pointList.push({ x: inPos.x, y: inPos.y });
    }

    if (isEnd) {
      if (this.typeId == 4 || this.typeId == 5 || this.typeId == 6) {
        var minx = Math.min(this.originData.pointList[0].x, this.originData.pointList[1].x);
        var miny = Math.min(this.originData.pointList[0].y, this.originData.pointList[1].y);
        var maxx = Math.max(this.originData.pointList[0].x, this.originData.pointList[1].x);
        var maxy = Math.max(this.originData.pointList[0].y, this.originData.pointList[1].y);
        this.originData.pointList[0] = { x: minx, y: miny };
        this.originData.pointList[1] = { x: maxx, y: maxy };
      }
      if (this.doAtAddEnd != null)
        this.doAtAddEnd();
    }
    this.addContents();
    this.addBoundBoxContents();
  };

  this.updateParams = function (params) {
    // this.originData.= e;

    this.originData.selectedFont = params.selectedFont;
    this.originData.selectedFontSize = params.selectedFontSize;

    this.originData.selectedBold = params.selectedBold;
    this.originData.selectedItalics = params.selectedItalics;
    this.originData.selectedUnderline = params.selectedUnderline;

    this.originData.selectedLineType = params.selectedLineType;
    this.originData.selectedLineWidth = params.selectedLineWidth;

    this.originData.selectedLineColor = params.selectedLineColor;
    this.originData.selectedFillColor = params.selectedFillColor;

    this.originData.selectedFillType = params.selectedFillType;

    if (params.text)
      this.originData.text = params.text;


    this.addContents();
    this.addBoundBoxContents();
  };

  // 点击选中
  if (this.boundBoxShap)
    this.boundBoxShap.on("click", this.onShapeClick)
  if (this.contentGroup)
    this.contentGroup.on("click", this.onShapeClick)
  if (this.contentGroupBottom)
    this.contentGroupBottom.on("click", this.onShapeClick)
}

MarkupBase.prototype.doAtAddEnd = function () {
  console.log("MarkupBase.doAtAddEnd")
}

/**
 * Markup draw a Rect
 * @param {*} originData 
 * @param {*} inTypeId  4 矩形（默认不填充）  5 矩形（默认填充）
 */
function MarkupRect(originData, inTypeId) {
  MarkupBase.call(this, originData, inTypeId);
  this.typeName = 'MarkupRect';
}

MarkupRect.prototype.addContents = function () {
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2

  if (this.contentShap == null)
    this.contentShap = this.contentGroup.append("rect");    // 标记 shape

  if (this.contentShapBottom == null)
    this.contentShapBottom = this.contentGroupBottom.append("rect");    // 标记 shape

  this.contentShap
    .attr("id", "content")
    .attr("x", function () {
      return Math.min(point1.x, point2.x)
    })
    .attr("y", function () {
      return Math.min(point1.y, point2.y);
    })
    .attr("width", function () {
      return Math.abs(point1.x - point2.x)
    })
    .attr("height", function () {
      return Math.abs(point1.y - point2.y)
    });

  this.contentShapBottom
    .attr("id", "content")
    .attr("x", function () {
      return Math.min(point1.x, point2.x)
    })
    .attr("y", function () {
      return Math.min(point1.y, point2.y);
    })
    .attr("width", function () {
      return Math.abs(point1.x - point2.x)
    })
    .attr("height", function () {
      return Math.abs(point1.y - point2.y)
    });

  this.apandBaseInfo();
  // this.contentShap.attr("visibility", "hidden");

};

/**
 * 包围盒及黑顶绘制 
 */
MarkupRect.prototype.addBoundBoxContents = function () {
  var _MarkupBaseSelf = this;
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2
  var minX = Math.min(point1.x, point2.x);
  var minY = Math.min(point1.y, point2.y);
  var width = Math.abs(point1.x - point2.x);
  var height = Math.abs(point1.y - point2.y);

  // var strokeWidth = this.originData.selectedLineWidth / 2;
  var strokeWidth = 0;

  /**
   * 盒子上黑点的数据 
   * 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   * 
   */
  var blockWidth = g_editDotWidth;
  // var blockWidth = 0;

  this.dotInfoList = [
    { x: minX - blockWidth - strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 0 },
    { x: minX + width / 2, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 1 },
    { x: minX + width + strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 2 },

    { x: minX - blockWidth - strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 3 },
    { x: minX + width + strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 4 },

    { x: minX - blockWidth - strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 5 },
    { x: minX + width / 2, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 6 },
    { x: minX + width + strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 7 },
  ];

  if (this.boundBoxShap == null)
    this.boundBoxShap = this.boundboxGroup.append("rect");

  this.boundBoxShap
    // .attr("x", minX - blockWidth - strokeWidth)
    // .attr("y", minY - blockWidth - strokeWidth)
    // .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    // .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("x", minX)
    .attr("y", minY)
    .attr("width", width)
    .attr("height", height)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000099")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  // 开始移动位置
  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  // 结束移动位置
  this.boundBoxShap.on("mouseup", function () {
    console.log("rect boundBoxShap mouseup")
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);

  });

  for (var i = 0; i < this.dotInfoList.length; i++) {
    var tempDotInfo = this.dotInfoList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      /**
       * optType: 0随便动 1上下 2 左右
       */
      dotInfoLeftBottom.optType = tempDotInfo.optType;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        if (d3.event.button != 0)
          return;
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      // tempDotShape.on("mouseup", function () {
      //   var dataindex = d3.select(this).attr("dataIndex");
      //   _MarkupBaseSelf.onBoundBoxDotMouseUp(dataindex);
      //   event.stopPropagation();//阻止事件冒泡
      //   event.preventDefault();  //阻止默认行为
      // });

      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", tempDotInfo.width)
      .attr("height", tempDotInfo.height)
      .attr("stroke", tempDotInfo.stroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", tempDotInfo.fill);
  }
}

/**
 * changing状态改变图形形状  
 * @param {*} index 
 * @param {*} mouseosX 
 * @param {*} mouseosY 
 */
MarkupRect.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  var dotInfo = this.boundboxDots[index];
  /**
   * box 0 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   */
  if (dotInfo.optType == 0) {
    if (mouseosY > this.originData.pointList[1].y - 10 || mouseosX > this.originData.pointList[1].x - 10)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 1) {
    if (mouseosY > this.originData.pointList[1].y - g_markupLineWidth)
      return;

    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 2) {
    if (mouseosY > this.originData.pointList[1].y - g_markupLineWidth
      || mouseosX < this.originData.pointList[0].x + g_markupLineWidth)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 3) {
    if (mouseosX > this.originData.pointList[1].x - g_markupLineWidth)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 4) {
    if (mouseosX < this.originData.pointList[0].x + g_markupLineWidth)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 5) {
    if (mouseosX > this.originData.pointList[1].x - g_markupLineWidth
      || mouseosY < this.originData.pointList[0].y + g_markupLineWidth)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 6) {
    if (mouseosY < this.originData.pointList[0].y + g_markupLineWidth)
      return;

    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 7) {
    if (mouseosX < this.originData.pointList[0].x + g_markupLineWidth
      || mouseosY < this.originData.pointList[0].y + g_markupLineWidth)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  }
};

/**
 * Markup draw a Line
 * @param {*} originData 
 * type  1  线段  2 多段线 3 多边形 8 自由画线
 */
function MarkupLine(originData, inTypeId) {
  MarkupBase.call(this, originData, inTypeId);
  this.typeName = 'MarkupLine';
}

MarkupLine.prototype.addContents = function () {
  var _self = this;
  if (this.contentShap == null)
    this.contentShap = this.contentGroup.append("path");    // 标记 shape
  if (this.contentShapBottom == null)
    this.contentShapBottom = this.contentGroupBottom.append("path");    // 标记 shape


  this.contentShap
    .attr("id", "content")
    .attr("d", function () {
      var re = "M";
      for (var i = 0; i < _self.originData.pointList.length; i++) {
        var temppos = _self.originData.pointList[i];
        if (i != 0)
          re += " L ";
        re += temppos.x + " " + temppos.y;
      }

      if (_self.typeId == "3")
        re += " Z";
      return re;
    });

  if (this.typeId == 3) {
    this.contentShapBottom
      .attr("id", "content")
      .attr("d", function () {
        var re = "M";
        for (var i = 0; i < _self.originData.pointList.length; i++) {
          var temppos = _self.originData.pointList[i];
          if (i != 0)
            re += " L ";
          re += temppos.x + " " + temppos.y;
        }

        if (_self.typeId == "3")
          re += " Z";
        return re;
      });
  }
  else {
    this.originData.selectedFillType = 0;
  }
  this.apandBaseInfo();
};

/**
 * 包围盒及黑顶绘制 
 */
MarkupLine.prototype.addBoundBoxContents = function () {
  var _MarkupBaseSelf = this;
  var minX = d3.min(this.originData.pointList, function (d) { return d.x; }),
    minY = d3.min(this.originData.pointList, function (d) { return d.y; }),
    maxX = d3.max(this.originData.pointList, function (d) { return d.x; }),
    maxY = d3.max(this.originData.pointList, function (d) { return d.y; });

  var width = Math.abs(maxX - minX);
  var height = Math.abs(maxY - minY);
  var blockWidth = g_editDotWidth;
  // var strokeWidth = this.originData.selectedLineWidth / 2;
  var strokeWidth = 0;

  if (this.boundBoxShap == null)
    this.boundBoxShap = this.boundboxGroup.append("rect");

  this.boundBoxShap
    .attr("x", minX - blockWidth - strokeWidth)
    .attr("y", minY - blockWidth - strokeWidth)
    .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000033")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("mouseup", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  for (var i = 0; i < this.originData.pointList.length; i++) {
    var tempDotInfo = this.originData.pointList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      dotInfoLeftBottom.optType = i;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      tempDotShape.on("mouseup", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseUp(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });


      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", g_editDotWidth)
      .attr("height", g_editDotWidth)
      .attr("stroke", g_editDotStroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", g_editDotFill);
  }
};

MarkupLine.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  if (index < this.originData.pointList.length) {
    this.originData.pointList[index].x = mouseosX;
    this.originData.pointList[index].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  }
};

/**
 * Markup draw a ellipse
 * @param {*} originData 
 * type  1  线段  2 多段线 3 多边形
 */
function MarkupEllipse(originData, inTypeId) {
  MarkupBase.call(this, originData, inTypeId);
  this.typeName = 'MarkupEllipse';
}


// cx="300" cy="150" rx="200" ry="80"
MarkupEllipse.prototype.addContents = function () {
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2

  if (this.contentShap == null)
    this.contentShap = this.contentGroup.append("ellipse");    // 标记 shape

  if (this.contentShapBottom == null)
    this.contentShapBottom = this.contentGroupBottom.append("ellipse");    // 标记 shape

  this.contentShap
    .attr("cx", function () {
      return point1.x + (point2.x - point1.x) / 2;
    })
    .attr("cy", function () {
      return point1.y + (point2.y - point1.y) / 2;
    })
    .attr("rx", function () {
      return Math.abs((point2.x - point1.x) / 2);
    })
    .attr("ry", function () {
      return Math.abs((point2.y - point1.y) / 2);
    });

  this.contentShapBottom
    .attr("cx", function () {
      return point1.x + (point2.x - point1.x) / 2;
    })
    .attr("cy", function () {
      return point1.y + (point2.y - point1.y) / 2;
    })
    .attr("rx", function () {
      return Math.abs((point2.x - point1.x) / 2);
    })
    .attr("ry", function () {
      return Math.abs((point2.y - point1.y) / 2);
    });

  this.apandBaseInfo();
};

/**
 * 包围盒及黑顶绘制 
 */
MarkupEllipse.prototype.addBoundBoxContents = function () {
  var _MarkupBaseSelf = this;
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2
  var minX = Math.min(point1.x, point2.x);
  var minY = Math.min(point1.y, point2.y);
  var width = Math.abs(point1.x - point2.x);
  var height = Math.abs(point1.y - point2.y);

  var strokeWidth = 0;

  /**
   * 盒子上黑点的数据 
   * 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   * 
   * var g_editDotStroke = "#000000"; // 包围盒黑点宽度
var g_editDotFill = "#000000"; // 包围盒黑点宽度

   */
  var blockWidth = g_editDotWidth;
  this.dotInfoList = [
    { x: minX - blockWidth - strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 0 },
    { x: minX + width / 2, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 1 },
    { x: minX + width + strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 2 },

    { x: minX - blockWidth - strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 3 },
    { x: minX + width + strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 4 },

    { x: minX - blockWidth - strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 5 },
    { x: minX + width / 2, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 6 },
    { x: minX + width + strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 7 },
  ];

  if (this.boundBoxShap == null)
    this.boundBoxShap = this.boundboxGroup.append("rect");

  this.boundBoxShap
    .attr("x", minX - blockWidth - strokeWidth)
    .attr("y", minY - blockWidth - strokeWidth)
    .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000033")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("mouseup", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
  });

  for (var i = 0; i < this.dotInfoList.length; i++) {
    var tempDotInfo = this.dotInfoList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      /**
       * optType: 0随便动 1上下 2 左右
       */
      dotInfoLeftBottom.optType = tempDotInfo.optType;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", tempDotInfo.width)
      .attr("height", tempDotInfo.height)
      .attr("stroke", tempDotInfo.stroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", tempDotInfo.fill);
  }
}

MarkupEllipse.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  var dotInfo = this.boundboxDots[index];
  /**
   * box 0 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   */
  if (dotInfo.optType == 0) {
    if (mouseosY > this.originData.pointList[1].y - 10 || mouseosX > this.originData.pointList[1].x - 10)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 1) {
    if (mouseosY > this.originData.pointList[1].y - 10)
      return;

    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 2) {
    if (mouseosY > this.originData.pointList[1].y - 10 || mouseosX < this.originData.pointList[0].x + 10)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 3) {
    if (mouseosX > this.originData.pointList[1].x - 10)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 4) {
    if (mouseosX < this.originData.pointList[0].x + 10)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 5) {
    if (mouseosX > this.originData.pointList[1].x - 10 || mouseosY < this.originData.pointList[0].y + 10)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 6) {
    if (mouseosY < this.originData.pointList[0].y + 10)
      return;

    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 7) {
    if (mouseosX < this.originData.pointList[0].x + 10 || mouseosY < this.originData.pointList[0].y + 10)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  }
};

/**
 * Markup draw a Arc
 * @param {*} originData 
 * type  1  线段  2 多段线 3 多边形
 */
function MarkupArc(originData, inTypeId) {
  MarkupBase.call(this, originData, inTypeId);
  this.typeName = 'MarkupArc';
}

// cx="300" cy="150" rx="200" ry="80"
MarkupArc.prototype.addContents = function () {
  /**
   * 平面三点定位算法
   * @param {*} x1 
   * @param {*} y1 
   * @param {*} x2 
   * @param {*} y2 
   * @param {*} x3 
   * @param {*} y3 
   */

  if (this.originData.pointList.length < 3)
    return;

  var centerInCircle = function (x1, y1, x2, y2, x3, y3) {
    var a;
    a = (y2 - y1) / (x2 - x1);
    var xMiddle = (x1 + x2) / 2;
    var yMiddle = (y1 + y2) / 2;
    var c, lastX, lastY;
    if (a != 0) {
      c = yMiddle - (-1 / a) * xMiddle;
      lastX = (Math.pow(x1, 2) + Math.pow(y1, 2) - Math.pow(x3, 2) - Math.pow(y3, 2) - 2 * c * y1 + 2 * c * y3) / (2 * ((x1 - x3) - (1 / a) * (y1 - y3)));
      lastY = (-1 / a) * lastX + c;
    } else {
      lastX = c = xMiddle;
      lastY = (Math.pow(x1, 2) + Math.pow(y1, 2) - Math.pow(x3, 2) - Math.pow(y3, 2) + 2 * lastX * (x3 - x1)) / (2 * (y1 - y3));
    }
    return { x: lastX, y: lastY }
  }
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2
  var point3 = this.originData.pointList[2]; // 点3

  // 1、2中点
  var pointC12 = { x: (point1.x + point2.x) / 2, y: (point1.y + point2.y) / 2 };
  // var pointC13 = { x: (point1.x + point3.x) / 2, y: (point1.y + point3.y) / 2 };
  // var pointC23 = { x: (point3.x + point2.x) / 2, y: (point3.y + point2.y) / 2 };

  // 圆心
  var circleCenter = centerInCircle(point1.x, point1.y, point2.x, point2.y, point3.x, point3.y);
  // 半径
  var circleRadius = Math.sqrt(Math.pow(point1.x - circleCenter.x, 2) + Math.pow(point1.y - circleCenter.y, 2));

  var dis3ToC12 = Math.sqrt(Math.pow(point3.x - pointC12.x, 2) + Math.pow(point3.y - pointC12.y, 2));
  var halfDis12 = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)) / 2;

  var isBigArc = dis3ToC12 > halfDis12 ? 1 : 0;


  var str = "M" + point1.x + " " + point1.y + " ";
  str += "A " + circleRadius + " " + circleRadius + " "; // 长短半径
  str += 0 + " "; // x-axis-rotation  旋转
  str += isBigArc + " "; // large-arc-flag  大小弧 0 小弧度
  str += 0 + " "; // sweep-flag  方向 0 逆时针
  str += point2.x + " " + point2.y + " ";

  if (this.originData.selectedFillType != 0)
    str += "Z";

  this.contentShap
  if (this.contentShap == null)
    this.contentShap = this.contentGroup.append("path")    // 标记 shape

  if (this.contentShapBottom == null)
    this.contentShapBottom = this.contentGroupBottom.append("path")    // 标记 shape

  this.contentShap
    .attr("d", str);

  this.contentShapBottom
    .attr("d", str);

  this.apandBaseInfo();
};

/**
 * 包围盒及黑顶绘制 
 */
MarkupArc.prototype.addBoundBoxContents = function () {
  var _MarkupBaseSelf = this;

  if (this.contentShap != null) {
    this.contentShap.on("mousedown", function () {
      var dataindex = d3.select(this).attr("dataIndex");
      _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
      event.stopPropagation();//阻止事件冒泡
      event.preventDefault();  //阻止默认行为
    });

    this.contentShap.on("mouseup", function () {
      var dataindex = d3.select(this).attr("dataIndex");
      _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
      event.stopPropagation();//阻止事件冒泡
      event.preventDefault();  //阻止默认行为
    });

  }

  for (var i = 0; i < this.originData.pointList.length; i++) {
    var tempDotInfo = this.originData.pointList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      dotInfoLeftBottom.optType = i;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      tempDotShape.on("mouseup", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseUp(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });


      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", g_editDotWidth)
      .attr("height", g_editDotWidth)
      .attr("stroke", g_editDotStroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", g_editDotFill);
  }
}

MarkupArc.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  if (index < this.originData.pointList.length) {
    this.originData.pointList[index].x = mouseosX;
    this.originData.pointList[index].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  }
};

/**
 * Markup draw a text
 * @param {*} originData 
 * type  10 文字
 */
function MarkupText(originData, inTypeId) {
  MarkupBase.call(this, originData, inTypeId);
  this.typeName = 'MarkupText';
}

MarkupText.prototype.addContents = function () {
  var _self = this;
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2
  var reCalShape = false;

  if (this.contentShap == null)
    this.contentShap = this.contentGroup.append("text")    // 标记 shape

  if (this.contentShap.attr("font-family") != this.originData.selectedFont ||
    this.contentShap.attr("font-size") != this.originData.selectedFontSize * 0.5 ||
    this.contentShap.text() != this.originData.text)
    reCalShape = true;

  this.contentShap
    .text(this.originData.text)
    .attr("x", function () {
      return 0;
    })
    .attr("y", function () {
      return 0;
    })
    .attr("fill", this.originData.selectedLineColor)
    .attr("font-size", this.originData.selectedFontSize * 0.5)
    .attr("lengthAdjust", "spacingAndGlyphs") // spacing  空间平均分配到文字间
    .attr("dominant-baseline", "ideographic") // 调整文字的基线
    .attr("text-decoration", this.originData.selectedUnderline ? "underline" : "none") // "underline")
    .attr("font-style", this.originData.selectedItalics ? "italic" : "normal")
    .attr("font-weight", this.originData.selectedBold ? "bold" : "normal")
    .attr("font-family", this.originData.selectedFont)
    .attr("textLength", 0)
    ;

  if (reCalShape) {
    var box1 = this.contentShap._groups;
    var box11 = box1[0][0];
    var boxx = box11.getBBox();

    this.originData.pointList[1] = { x: point1.x + boxx.width, y: point1.y + boxx.height }; // 点2
    point2 = this.originData.pointList[1];
  }

  this.contentShap.attr("transform", function () {
    var scalex = 1;
    var scaley = -1;
    var minx = Math.min(point1.x, point2.x);
    var miny = Math.min(point1.y, point2.y) - Math.abs(point1.y - point2.y);

    var str = '';
    str += "scale(" + scalex + "," + scaley + ") ";
    str += "translate(" + minx + "," + (0 - miny) + ")";

    return str;
  })
  this.contentShap.attr("textLength", Math.abs(point1.x - point2.x));


  // try {
  //   var box0 = this.contentShap._groups;
  //   var box00 = box0[0][0];

  //   var box = box00.getBoundingClientRect();
  //   console.log("box");

  //   console.log(box);
  // } catch (error) {
  //   console.log(error)
  // }

  try {

    // ok
    var box1 = this.contentShap._groups;
    var box11 = box1[0][0];

    var boxx = box11.getBBox();

  } catch (error) {
    console.log(error)
  }
};

/**
 * 包围盒及黑顶绘制 
 */
MarkupText.prototype.addBoundBoxContents = function () {
  var _MarkupBaseSelf = this;
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2
  var minX = Math.min(point1.x, point2.x);
  var minY = Math.min(point1.y, point2.y) - Math.abs(point1.y - point2.y);
  var width = Math.abs(point1.x - point2.x);
  var height = Math.abs(point1.y - point2.y);

  var strokeWidth = 0;

  /**
   * 盒子上黑点的数据 
   * 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   * 
   * var g_editDotStroke = "#000000"; // 包围盒黑点宽度
var g_editDotFill = "#000000"; // 包围盒黑点宽度

   */
  var blockWidth = g_editDotWidth;
  this.dotInfoList = [
    { x: minX - blockWidth - strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 0 },
    { x: minX + width / 2, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 1 },
    { x: minX + width + strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 2 },

    { x: minX - blockWidth - strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 3 },
    { x: minX + width + strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 4 },

    { x: minX - blockWidth - strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 5 },
    { x: minX + width / 2, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 6 },
    { x: minX + width + strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 7 },
  ];

  if (this.boundBoxShap == null) {
    this.boundBoxShap = this.boundboxGroup.append("rect");

    this.boundBoxShap.on("dblclick", function () {
      g_openTextInputFun(_MarkupBaseSelf.originData.text);
      event.stopPropagation();//阻止事件冒泡
      event.preventDefault();  //阻止默认行为
    })
  }

  this.boundBoxShap
    .attr("x", minX - blockWidth - strokeWidth)
    .attr("y", minY - blockWidth - strokeWidth)
    .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000033")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("mouseup", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
  });

  for (var i = 0; i < this.dotInfoList.length; i++) {
    var tempDotInfo = this.dotInfoList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      /**
       * optType: 0随便动 1上下 2 左右
       */
      dotInfoLeftBottom.optType = tempDotInfo.optType;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        if (d3.event.button != 0)
          return;

        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", tempDotInfo.width)
      .attr("height", tempDotInfo.height)
      .attr("stroke", tempDotInfo.stroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", tempDotInfo.fill);
  }
}

MarkupText.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  var dotInfo = this.boundboxDots[index];
  /**
   * box 0 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   */
  if (dotInfo.optType == 0) {
    if (mouseosY > this.originData.pointList[1].y - 10 || mouseosX > this.originData.pointList[1].x - 10)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 1) {
    if (mouseosY > this.originData.pointList[1].y - 10)
      return;

    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 2) {
    if (mouseosY > this.originData.pointList[1].y - 10 || mouseosX < this.originData.pointList[0].x + 10)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.originData.pointList[0].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 3) {
    if (mouseosX > this.originData.pointList[1].x - 10)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 4) {
    if (mouseosX < this.originData.pointList[0].x + 10)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 5) {
    if (mouseosX > this.originData.pointList[1].x - 10 || mouseosY < this.originData.pointList[0].y + 10)
      return;

    this.originData.pointList[0].x = mouseosX;
    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 6) {
    if (mouseosY < this.originData.pointList[0].y + 10)
      return;

    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  } else if (dotInfo.optType == 7) {
    if (mouseosX < this.originData.pointList[0].x + 10 || mouseosY < this.originData.pointList[0].y + 10)
      return;

    this.originData.pointList[1].x = mouseosX;
    this.originData.pointList[1].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  }
};

/**
 * Markup draw a Draw
 * @param {*} originData 
 * type 8 自由画线 9 cloud
 */
function MarkupHandDraw(originData, inTypeId) {
  MarkupBase.call(this, originData, inTypeId);
  this.typeName = 'MarkupHandDraw';
}

MarkupHandDraw.prototype.addContents = function () {
  var _self = this;
  if (this.contentShap == null)
    this.contentShap = this.contentGroup.append("path");    // 标记 shape

  this.contentShap
    .attr("id", "content")
    .attr("d", function () {
      var re = "M";
      for (var i = 0; i < _self.originData.pointList.length; i++) {
        var temppos = _self.originData.pointList[i];
        if (i != 0)
          re += " L ";
        re += temppos.x + " " + temppos.y;
      }
      return re;
    });

  _self.originData.selectedFillType = 0;
  this.apandBaseInfo();
};

/**
 * 包围盒及黑点绘制 
 */
MarkupHandDraw.prototype.addBoundBoxContents = function () {

  var minX = d3.min(this.originData.pointList, function (d) { return d.x; }),
    minY = d3.min(this.originData.pointList, function (d) { return d.y; }),
    maxX = d3.max(this.originData.pointList, function (d) { return d.x; }),
    maxY = d3.max(this.originData.pointList, function (d) { return d.y; });
  var _MarkupBaseSelf = this;
  var width = Math.abs(maxX - minX);
  var height = Math.abs(maxY - minY);
  var strokeWidth = 0;

  /**
   * 盒子上黑点的数据 
   * 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   * 
   * var g_editDotStroke = "#000000"; // 包围盒黑点宽度
var g_editDotFill = "#000000"; // 包围盒黑点宽度
 
   */
  var blockWidth = g_editDotWidth;
  this.dotInfoList = [
    { x: minX - blockWidth - strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 0 },
    { x: minX + width / 2, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 1 },
    { x: minX + width + strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 2 },

    { x: minX - blockWidth - strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 3 },
    { x: minX + width + strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 4 },

    { x: minX - blockWidth - strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 5 },
    { x: minX + width / 2, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 6 },
    { x: minX + width + strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 7 },
  ];

  if (this.boundBoxShap == null)
    this.boundBoxShap = this.boundboxGroup.append("rect");

  this.boundBoxShap
    .attr("x", minX - blockWidth - strokeWidth)
    .attr("y", minY - blockWidth - strokeWidth)
    .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000033")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("mouseup", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
  });

  for (var i = 0; i < this.dotInfoList.length; i++) {
    var tempDotInfo = this.dotInfoList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      /**
       * optType: 0随便动 1上下 2 左右
       */
      dotInfoLeftBottom.optType = tempDotInfo.optType;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", tempDotInfo.width)
      .attr("height", tempDotInfo.height)
      .attr("stroke", tempDotInfo.stroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", tempDotInfo.fill);
  }
}

MarkupHandDraw.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  var dotInfo = this.boundboxDots[index];
  var minX = d3.min(this.originData.pointList, function (d) { return d.x; }),
    minY = d3.min(this.originData.pointList, function (d) { return d.y; }),
    maxX = d3.max(this.originData.pointList, function (d) { return d.x; }),
    maxY = d3.max(this.originData.pointList, function (d) { return d.y; });

  var widthO = Math.abs(maxX - minX);
  var heightO = Math.abs(maxY - minY);
  var widthN = 1;
  var heightN = 1;
  var minXN = 1;
  var minYN = 1;
  var maxXN = 1;
  var maxYN = 1;

  /**
   * box 0 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   */
  if (dotInfo.optType == 0) {
    if (mouseosY > maxY - 10 || mouseosX > maxX - 10)
      return;
    minXN = mouseosX;
    minYN = mouseosY;
    maxXN = maxX;
    maxYN = maxY;
  } else if (dotInfo.optType == 1) {
    if (mouseosY > maxY - 10)
      return;

    minXN = minX;
    minYN = mouseosY;
    maxXN = maxX;
    maxYN = maxY;
  } else if (dotInfo.optType == 2) {
    if (mouseosY > maxY - 10 || mouseosX < minX + 10)
      return;

    minXN = minX;
    minYN = mouseosY;
    maxXN = mouseosX;
    maxYN = maxY;
  } else if (dotInfo.optType == 3) {
    if (mouseosX > maxX - 10)
      return;

    minXN = mouseosX;
    minYN = minY;
    maxXN = maxX;
    maxYN = maxY;
  } else if (dotInfo.optType == 4) {
    if (mouseosX < minX + 10)
      return;

    minXN = minX;
    minYN = minY;
    maxXN = mouseosX;
    maxYN = maxY;
  } else if (dotInfo.optType == 5) {
    if (mouseosX > maxX - 10 || mouseosY < minY + 10)
      return;

    minXN = mouseosX;
    minYN = minY;
    maxXN = maxX;
    maxYN = mouseosY;
  } else if (dotInfo.optType == 6) {
    if (mouseosY < minY + 10)
      return;

    minXN = minX;
    minYN = minY;
    maxXN = maxX;
    maxYN = mouseosY;
  } else if (dotInfo.optType == 7) {
    if (mouseosX < minX + 10 || mouseosY < minY + 10)
      return;

    minXN = minX;
    minYN = minY;
    maxXN = mouseosX;
    maxYN = mouseosY;
  }
  widthN = maxXN - minXN;
  heightN = maxYN - minYN;

  for (var i = 0; i < this.originData.pointList.length; i++) {
    var tempPoint = this.originData.pointList[i];
    var xN = (((tempPoint.x - minX) / widthO) * widthN) + minXN;
    var yN = (((tempPoint.y - minY) / heightO) * heightN) + minYN;

    tempPoint.x = xN;
    tempPoint.y = yN;
  }
  this.addContents();
  this.addBoundBoxContents();
};

///////////////////////////////////////////////////
/**
 * Markup draw a Draw
 * @param {*} originData 
 * type 9 cloud
 */
function MarkupCloudDraw(originData, inTypeId) {
  this.arcShapes = [null, null, null, null, null, null];
  this.polyShape = null;
  this.arcShapesBottom = [null, null, null, null, null, null];
  this.polyShapeBottom = null;
  this.arcCDatas = null;

  this.typeName = 'MarkupCloudDraw';
  MarkupBase.call(this, originData, inTypeId);
}
MarkupCloudDraw.prototype.addContents = function () {
  var _self = this;
  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2
  var widthWhole = Math.abs(point1.x - point2.x);
  var heightWhole = Math.abs(point1.y - point2.y);

  var MINX = Math.min(point1.x, point2.x);
  var MINY = Math.min(point1.y, point2.y);
  var MAXX = Math.max(point1.x, point2.x);
  var MAXY = Math.max(point1.y, point2.y);

  var minX = Math.min(point1.x, point2.x) + widthWhole / 5;
  var minY = Math.min(point1.y, point2.y) + heightWhole / 5;
  var maxX = Math.max(point1.x, point2.x) - widthWhole / 5;
  var maxY = Math.max(point1.y, point2.y) - heightWhole / 5;

  var width = Math.abs(minX - maxX);
  var height = Math.abs(minY - maxY);
  var O = { x: minX + width / 2, y: minY + height / 2 };

  _self.arcCDatas = [
    { // 0
      startPos: {
        x: maxX, y: O.y + height / 4
      },
      endPos: {
        x: O.x, y: maxY
      },
      controllPos: [
        {
          x: maxX, y: MAXY
        },
        {
          x: O.x, y: MAXY
        },
      ]
    }, { // 1
      startPos: {
        x: O.x, y: maxY,
      },
      endPos: {
        x: minX, y: O.y + height / 4
      },
      controllPos: [
        {
          x: O.x, y: MAXY
        },
        {
          x: minX, y: MAXY
        },
      ]
    }, { // 2
      startPos: {
        x: minX, y: O.y + height / 4
      },
      endPos: {
        x: minX, y: O.y - height / 4,
      },
      controllPos: [
        {
          x: MINX, y: O.y + height / 4
        },
        {
          x: MINX, y: O.y - height / 4
        },
      ]
    }, { // 3
      startPos: {
        x: minX, y: O.y - height / 4
      },
      endPos: {
        x: O.x, y: minY
      },
      controllPos: [
        {
          x: minX, y: MINY
        },
        {
          x: O.x, y: MINY
        },
      ]
    }, { // 4
      startPos: {
        x: O.x, y: minY
      },
      endPos: {
        x: maxX, y: O.y - height / 4
      },
      controllPos: [
        {
          x: O.x, y: MINY
        },
        {
          x: maxX, y: MINY
        },
      ]
    }, { // 5
      startPos: {
        x: maxX, y: O.y - height / 4
      },
      endPos: {
        x: maxX, y: O.y + height / 4
      },
      controllPos: [
        {
          x: MAXX, y: O.y - height / 4
        },
        {
          x: MAXX, y: O.y + height / 4
        },
      ]
    }
  ]

  var updateArc = function (arcshape, arcData) {
    var str = "M" + arcData.startPos.x + " " + arcData.startPos.y + " ";
    str += "C " + arcData.controllPos[0].x + " " + arcData.controllPos[0].y + ", "; // 长短半径
    str += arcData.controllPos[1].x + " " + arcData.controllPos[1].y + ", "; // 长短半径
    str += arcData.endPos.x + " " + arcData.endPos.y + " ";

    arcshape
      .attr("d", str);
    return arcshape;
  }

  for (var i = 0; i < _self.arcCDatas.length; i++) {
    var temparc = null;
    if (_self.arcShapes[i] == null) {
      temparc = _self.contentGroup.append("path")    // 标记 shape
      _self.arcShapes[i] = temparc;
    }
    else
      temparc = _self.arcShapes[i];
    updateArc(temparc, _self.arcCDatas[i]);


    var temparcbottom = null;
    if (_self.arcShapesBottom[i] == null) {
      temparcbottom = _self.contentGroupBottom.append("path")    // 标记 shape
      _self.arcShapesBottom[i] = temparcbottom;
    }
    else
      temparcbottom = _self.arcShapesBottom[i];
    updateArc(temparcbottom, _self.arcCDatas[i]);
  }

  if (_self.polyShape == null) {
    _self.polyShape = _self.contentGroup.append("path")    // 标记 shape
  }

  if (_self.polyShapeBottom == null) {
    _self.polyShapeBottom = _self.contentGroupBottom.append("path")    // 标记 shape
  }

  _self.polyShape
    .attr("d", function () {
      var re = "M";
      for (var i = 0; i < _self.arcCDatas.length; i++) {
        var temppos = _self.arcCDatas[i];
        if (i != 0)
          re += " L ";
        re += temppos.startPos.x + " " + temppos.startPos.y;
      }

      if (_self.typeId == "3")
        re += " Z";
      return re;
    });

  _self.polyShapeBottom
    .attr("d", function () {
      var re = "M";
      for (var i = 0; i < _self.arcCDatas.length; i++) {
        var temppos = _self.arcCDatas[i];
        if (i != 0)
          re += " L ";
        re += temppos.startPos.x + " " + temppos.startPos.y;
      }

      if (_self.typeId == "3")
        re += " Z";
      return re;
    });

  this.apandArcBaseInfo();
};

MarkupCloudDraw.prototype.apandArcBaseInfo = function () {
  var nRGBLColor = this.originData.selectedLineColor;// 线色
  var nRGBFillColor = this.originData.selectedFillColor;// 填充颜色
  var sFillType = this.originData.selectedFillType;// 填充类型 1 填充 2 填充  置于底层
  var sLineStyle = this.originData.selectedLineType;// 线型
  var wLineThick = this.originData.selectedLineWidth;// 线宽

  for (var i = 0; i < 6; i++) {
    var tempArc = this.arcShapes[i];
    var tempArcBottom = this.arcShapesBottom[i];

    if (tempArc == null)
      continue;

    if (nRGBLColor) {
      tempArc.attr("stroke", nRGBLColor);
    }

    if (wLineThick) {
      tempArc.attr("stroke-width", g_markupLineWidth * wLineThick / 2);
    }

    // fill   sFillType == 0 ? "#00000000" :
    var fillcolor = nRGBFillColor;
    tempArc.attr("fill", sFillType == 1 ? fillcolor : "#00000000");
    tempArcBottom.attr("fill", sFillType == 2 ? fillcolor : "#00000000");

    if (sLineStyle != 0) {
      tempArc.attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[sLineStyle]);
    }
  }
  var fillcolor = nRGBFillColor;
  this.polyShape.attr("fill", sFillType == 1 ? fillcolor : "#00000000");
  this.polyShapeBottom.attr("fill", sFillType == 2 ? fillcolor : "#00000000");
  this.polyShapeBottom.attr("stroke-width", 0);
}

/**
 * 包围盒及黑点绘制 
 */
MarkupCloudDraw.prototype.addBoundBoxContents = function () {

  var minX = d3.min(this.originData.pointList, function (d) { return d.x; }),
    minY = d3.min(this.originData.pointList, function (d) { return d.y; }),
    maxX = d3.max(this.originData.pointList, function (d) { return d.x; }),
    maxY = d3.max(this.originData.pointList, function (d) { return d.y; });

  var point1 = this.originData.pointList[0]; // 点1
  var point2 = this.originData.pointList[1]; // 点2
  minX = Math.min(point1.x, point2.x);
  minY = Math.min(point1.y, point2.y);
  maxX = Math.max(point1.x, point2.x);
  maxY = Math.max(point1.y, point2.y);

  var _MarkupBaseSelf = this;
  var width = Math.abs(maxX - minX);
  var height = Math.abs(maxY - minY);
  var strokeWidth = 0;

  /**
   * 盒子上黑点的数据 
   * 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   * 
   * var g_editDotStroke = "#000000"; // 包围盒黑点宽度
var g_editDotFill = "#000000"; // 包围盒黑点宽度
 
   */
  var blockWidth = g_editDotWidth;
  this.dotInfoList = [
    { x: minX - blockWidth - strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 0 },
    { x: minX + width / 2, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 1 },
    { x: minX + width + strokeWidth, y: minY - blockWidth - strokeWidth, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 2 },

    { x: minX - blockWidth - strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 3 },
    { x: minX + width + strokeWidth, y: minY + height / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 4 },

    { x: minX - blockWidth - strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 5 },
    { x: minX + width / 2, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 6 },
    { x: minX + width + strokeWidth, y: minY + height + strokeWidth + g_editDotWidth - blockWidth / 2, width: blockWidth, height: blockWidth, stroke: g_editDotStroke, fill: g_editDotStroke, optType: 7 },
  ];

  if (this.boundBoxShap == null)
    this.boundBoxShap = this.boundboxGroup.append("rect");

  this.boundBoxShap
    .attr("x", minX - blockWidth - strokeWidth)
    .attr("y", minY - blockWidth - strokeWidth)
    .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000033")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("mouseup", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
  });

  for (var i = 0; i < this.dotInfoList.length; i++) {
    var tempDotInfo = this.dotInfoList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      /**
       * optType: 0随便动 1上下 2 左右
       */
      dotInfoLeftBottom.optType = tempDotInfo.optType;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", tempDotInfo.width)
      .attr("height", tempDotInfo.height)
      .attr("stroke", tempDotInfo.stroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", tempDotInfo.fill);
  }
}

MarkupCloudDraw.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  var dotInfo = this.boundboxDots[index];
  var minX = d3.min(this.originData.pointList, function (d) { return d.x; }),
    minY = d3.min(this.originData.pointList, function (d) { return d.y; }),
    maxX = d3.max(this.originData.pointList, function (d) { return d.x; }),
    maxY = d3.max(this.originData.pointList, function (d) { return d.y; });

  var widthO = Math.abs(maxX - minX);
  var heightO = Math.abs(maxY - minY);
  var widthN = 1;
  var heightN = 1;
  var minXN = 1;
  var minYN = 1;
  var maxXN = 1;
  var maxYN = 1;

  /**
   * box 0 左下  中下  右下  左中 （中中） 右中 左上 中上 右上
   */
  if (dotInfo.optType == 0) {
    if (mouseosY > maxY - 10 || mouseosX > maxX - 10)
      return;
    minXN = mouseosX;
    minYN = mouseosY;
    maxXN = maxX;
    maxYN = maxY;
  } else if (dotInfo.optType == 1) {
    if (mouseosY > maxY - 10)
      return;

    minXN = minX;
    minYN = mouseosY;
    maxXN = maxX;
    maxYN = maxY;
  } else if (dotInfo.optType == 2) {
    if (mouseosY > maxY - 10 || mouseosX < minX + 10)
      return;

    minXN = minX;
    minYN = mouseosY;
    maxXN = mouseosX;
    maxYN = maxY;
  } else if (dotInfo.optType == 3) {
    if (mouseosX > maxX - 10)
      return;

    minXN = mouseosX;
    minYN = minY;
    maxXN = maxX;
    maxYN = maxY;
  } else if (dotInfo.optType == 4) {
    if (mouseosX < minX + 10)
      return;

    minXN = minX;
    minYN = minY;
    maxXN = mouseosX;
    maxYN = maxY;
  } else if (dotInfo.optType == 5) {
    if (mouseosX > maxX - 10 || mouseosY < minY + 10)
      return;

    minXN = mouseosX;
    minYN = minY;
    maxXN = maxX;
    maxYN = mouseosY;
  } else if (dotInfo.optType == 6) {
    if (mouseosY < minY + 10)
      return;

    minXN = minX;
    minYN = minY;
    maxXN = maxX;
    maxYN = mouseosY;
  } else if (dotInfo.optType == 7) {
    if (mouseosX < minX + 10 || mouseosY < minY + 10)
      return;

    minXN = minX;
    minYN = minY;
    maxXN = mouseosX;
    maxYN = mouseosY;
  }
  widthN = maxXN - minXN;
  heightN = maxYN - minYN;

  for (var i = 0; i < this.originData.pointList.length; i++) {
    var tempPoint = this.originData.pointList[i];
    var xN = (((tempPoint.x - minX) / widthO) * widthN) + minXN;
    var yN = (((tempPoint.y - minY) / heightO) * heightN) + minYN;

    tempPoint.x = xN;
    tempPoint.y = yN;
  }
  this.addContents();
  this.addBoundBoxContents();
};
///////////////////////////////////////////////////
/**
 * Markup draw a Arrow Polyline And Text
 * @param {*} originData 
 * type 11 
 */
function MarkupPolylineAndText(originData, inTypeId) {
  this.typeName = 'MarkupPolylineAndText';
  this._polylineShap = null;
  this._arrowLine = null;
  this._textShap = null;
  MarkupBase.call(this, originData, inTypeId);
}

MarkupPolylineAndText.prototype.addContents = function () {
  var _self = this;
  if (this._polylineShap == null)
    this._polylineShap = this.contentGroup.append("path");    // 标记 shape

  this._polylineShap
    .attr("d", function () {
      var re = "M";
      for (var i = 0; i < _self.originData.pointList.length; i++) {
        var temppos = _self.originData.pointList[i];
        if (i != 0)
          re += " L ";
        re += temppos.x + " " + temppos.y;
      }
      return re;
    });

  // arrow
  if (this._arrowLine == null)
    this._arrowLine = this.contentGroup.append("path");    // 标记 shape

  var baseVector = {
    x: _self.originData.pointList[1].x - _self.originData.pointList[0].x,
    y: _self.originData.pointList[1].y - _self.originData.pointList[0].y
  };

  var baseNormalVector = {
    x: _self.originData.pointList[1].y - _self.originData.pointList[0].y,
    y: _self.originData.pointList[0].x - _self.originData.pointList[1].x
  };

  var arrowCenterPointInLine = movePointByVector(baseVector, _self.originData.pointList[0], 3);
  var arrowDot0 = movePointByVector(baseNormalVector, arrowCenterPointInLine, 1);
  var arrowDot1 = movePointByVector(baseNormalVector, arrowCenterPointInLine, -1);

  this._arrowLine
    .attr("d", function () {
      var re = "M";
      re += arrowDot0.x + " " + arrowDot0.y;
      re += " L ";
      re += _self.originData.pointList[0].x + " " + _self.originData.pointList[0].y;
      re += " L ";
      re += arrowDot1.x + " " + arrowDot1.y;
      return re;
    });
  // arrow


  // text
  var _textPoint = this.originData.pointList[this.originData.pointList.length - 1]; // 点1
  if (this._textShap == null)
    this._textShap = this.contentGroup.append("text")    // 标记 shape

  this._textShap
    .text(this.originData.text)
    .attr("x", function () {
      return 0;
    })
    .attr("y", function () {
      return 0;
    })
    .attr("fill", this.originData.selectedLineColor)
    .attr("font-size", this.originData.selectedFontSize * 0.5)
    .attr("lengthAdjust", "spacingAndGlyphs") // spacing  空间平均分配到文字间
    .attr("dominant-baseline", "ideographic") // 调整文字的基线
    .attr("text-decoration", this.originData.selectedUnderline ? "underline" : "none") // "underline")
    .attr("font-style", this.originData.selectedItalics ? "italic" : "normal")
    .attr("font-weight", this.originData.selectedBold ? "bold" : "normal")
    .attr("font-family", this.originData.selectedFont)
    ;

  this._textShap.attr("transform", function () {
    var scalex = 1;
    var scaley = -1;
    var str = '';
    str += "scale(" + scalex + "," + scaley + ") ";
    str += "translate(" + _textPoint.x + "," + (0 - _textPoint.y + _self.originData.selectedFontSize * 1.1) + ")";

    return str;
  })
  // text

  this.apandBaseInfoExt();
};

/**
 * 包围盒及黑顶绘制 
 */
MarkupPolylineAndText.prototype.addBoundBoxContents = function () {
  var _MarkupBaseSelf = this;
  var minX = d3.min(this.originData.pointList, function (d) { return d.x; }),
    minY = d3.min(this.originData.pointList, function (d) { return d.y; }),
    maxX = d3.max(this.originData.pointList, function (d) { return d.x; }),
    maxY = d3.max(this.originData.pointList, function (d) { return d.y; });

  var width = Math.abs(maxX - minX);
  var height = Math.abs(maxY - minY);
  var blockWidth = g_editDotWidth;
  // var strokeWidth = this.originData.selectedLineWidth / 2;
  var strokeWidth = 0;

  if (this.boundBoxShap == null)
    this.boundBoxShap = this.boundboxGroup.append("rect");

  this.boundBoxShap
    .attr("x", minX - blockWidth - strokeWidth)
    .attr("y", minY - blockWidth - strokeWidth)
    .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000033")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("mouseup", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("dblclick", function () {
    g_openTextInputFun(_MarkupBaseSelf.originData.text);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  })

  for (var i = 0; i < this.originData.pointList.length; i++) {
    var tempDotInfo = this.originData.pointList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      dotInfoLeftBottom.optType = i;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      tempDotShape.on("mouseup", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseUp(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });


      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", g_editDotWidth)
      .attr("height", g_editDotWidth)
      .attr("stroke", g_editDotStroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", g_editDotFill);
  }
};

MarkupPolylineAndText.prototype.apandBaseInfoExt = function () {
  var nRGBLColor = this.originData.selectedLineColor;// 线色
  var sLineStyle = this.originData.selectedLineType;// 线型
  var wLineThick = this.originData.selectedLineWidth;// 线宽

  if (nRGBLColor) {
    this._polylineShap.attr("stroke", nRGBLColor);
    this._arrowLine.attr("stroke", nRGBLColor);

  }

  if (wLineThick) {
    this._polylineShap.attr("stroke-width", g_markupLineWidth * wLineThick / 2);
    this._arrowLine.attr("stroke-width", g_markupLineWidth * wLineThick / 2);
  }

  if (sLineStyle != 0) {
    this._polylineShap.attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[sLineStyle]);
    this._arrowLine.attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[sLineStyle]);
  }

  this._polylineShap.attr("fill", "#00000000");
  this._arrowLine.attr("fill", "#00000000");
}

MarkupPolylineAndText.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  if (index < this.originData.pointList.length) {
    this.originData.pointList[index].x = mouseosX;
    this.originData.pointList[index].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  }
};

/**
 * 球标 13 - 16
 */
function MarkupBallMarker(originData, inTypeId) {
  this.typeName = 'MarkupBallMarker';
  this._polylineShap = null;
  this._textShap = null;
  this._ballShap = null;
  this._ballShapBottom = null;
  MarkupBase.call(this, originData, inTypeId);
}

MarkupBallMarker.prototype.addContents = function () {
  var _self = this;
  if (this._polylineShap == null) {
    this._polylineShap = this.contentGroup.append("path");    // 标记 shape
    this._polylineShap.attr("id", "ball_polyline");
  }

  this._polylineShap
    .attr("d", function () {
      var re = "M";
      for (var i = 0; i < _self.originData.pointList.length; i++) {
        var temppos = _self.originData.pointList[i];
        if (i != 0)
          re += " L ";
        re += temppos.x + " " + temppos.y;
      }
      return re;
    });

  if (this._textShap == null) {
    this._textShap = this.contentGroup.append("text");    // 标记 shape
  }

  this._textShap
    // .text(this.originData.text)
    .text("-1")
    .attr("x", function () {
      return 0;
    })
    .attr("y", function () {
      return 0;
    })
    .attr("fill", "#FF0000")
    .attr("font-size", this.originData.selectedFontSize * 0.5)
    .attr("lengthAdjust", "spacingAndGlyphs") // spacing  空间平均分配到文字间
    .attr("dominant-baseline", "ideographic") // 调整文字的基线
    .attr("text-decoration", this.originData.selectedUnderline ? "underline" : "none") // "underline")
    .attr("font-style", this.originData.selectedItalics ? "italic" : "normal")
    .attr("font-weight", this.originData.selectedBold ? "bold" : "normal")
    .attr("font-family", this.originData.selectedFont)
    ;

  if (this._ballShap != null) {
    var lastPos1 = _self.originData.pointList[_self.originData.pointList.length - 1];
    var lastPos0 = _self.originData.pointList[_self.originData.pointList.length - 2];
    var baseVector = {
      x: lastPos1.x - lastPos0.x,
      y: lastPos1.y - lastPos0.y
    };
    var shapeRadius = this.originData.selectedFontSize * 0.6;
    var centerPos = movePointByVector(baseVector, lastPos1, shapeRadius);

    if (this._textShap != null) {
      this._textShap.attr("transform", function () {
        var scalex = 1;
        var scaley = -1;
        var str = '';
        str += "scale(" + scalex + "," + scaley + ") ";
        str += "translate(" + (centerPos.x - (_self.originData.selectedFontSize / 4)) + "," + (0 - centerPos.y + (_self.originData.selectedFontSize / 2)) + ")";

        return str;
      })
    }



    if (this.typeId == 13) {
      this._ballShap.attr("cx", function () {
        return centerPos.x;
      })
        .attr("cy", function () {
          return centerPos.y;
        })
        .attr("rx", function () {
          return shapeRadius;
        })
        .attr("ry", function () {
          return shapeRadius;
        });

      this._ballShapBottom.attr("cx", function () {
        return centerPos.x;
      })
        .attr("cy", function () {
          return centerPos.y;
        })
        .attr("rx", function () {
          return shapeRadius;
        })
        .attr("ry", function () {
          return shapeRadius;
        });
    } else if (this.typeId == 14) {
      this._ballShap.attr("x", function () {
        return centerPos.x - shapeRadius;
      })
        .attr("y", function () {
          return centerPos.y - shapeRadius
        })
        .attr("width", function () {
          return shapeRadius * 2
        })
        .attr("height", function () {
          return shapeRadius * 2
        });

      this._ballShapBottom.attr("x", function () {
        return centerPos.x - shapeRadius;
      })
        .attr("y", function () {
          return centerPos.y - shapeRadius
        })
        .attr("width", function () {
          return shapeRadius * 2
        })
        .attr("height", function () {
          return shapeRadius * 2
        });
    } else if (this.typeId == 15) {
      this._ballShap.attr("d", function () {
        var re = "M ";
        re += centerPos.x + " " + (centerPos.y + shapeRadius * 1.2);
        re += " L ";
        re += (centerPos.x - shapeRadius / 0.8) + " " + (centerPos.y - shapeRadius / 1.2);
        re += " L ";
        re += (centerPos.x + shapeRadius / 0.8) + " " + (centerPos.y - shapeRadius / 1.2);
        re += " Z";
        return re;

      });

      this._ballShapBottom.attr("d", function () {
        var re = "M ";
        re += centerPos.x + " " + (centerPos.y + shapeRadius * 1.2);
        re += " L ";
        re += (centerPos.x - shapeRadius / 0.8) + " " + (centerPos.y - shapeRadius / 1.2);
        re += " L ";
        re += (centerPos.x + shapeRadius / 0.8) + " " + (centerPos.y - shapeRadius / 1.2);
        re += " Z";
        return re;

      });
    } else if (this.typeId == 16) {
      this._ballShap.attr("d", function () {
        var re = "M ";
        re += (centerPos.x - shapeRadius) + " " + centerPos.y;
        re += " L ";
        re += (centerPos.x) + " " + (centerPos.y + shapeRadius);
        re += " L ";
        re += (centerPos.x + shapeRadius) + " " + (centerPos.y);
        re += " L ";
        re += (centerPos.x) + " " + (centerPos.y - shapeRadius);
        re += " Z";
        return re;

      });

      this._ballShapBottom.attr("d", function () {
        var re = "M ";
        re += (centerPos.x - shapeRadius) + " " + centerPos.y;
        re += " L ";
        re += (centerPos.x) + " " + (centerPos.y + shapeRadius);
        re += " L ";
        re += (centerPos.x + shapeRadius) + " " + (centerPos.y);
        re += " L ";
        re += (centerPos.x) + " " + (centerPos.y - shapeRadius);
        re += " Z";
        return re;

      });
    }
  }

  this.apandBaseInfoExt();
};

MarkupBallMarker.prototype.apandBaseInfoExt = function () {
  var nRGBLColor = this.originData.selectedLineColor;// 线色
  var sLineStyle = this.originData.selectedLineType;// 线型
  var wLineThick = this.originData.selectedLineWidth;// 线宽
  var nRGBFillColor = this.originData.selectedFillColor;// 填充颜色
  var sFillType = this.originData.selectedFillType;// 填充类型 1 填充 2 填充  置于底层

  if (nRGBLColor) {
    this._polylineShap.attr("stroke", nRGBLColor);
    if (this._ballShap != null)
      this._ballShap.attr("stroke", nRGBLColor);
  }

  if (wLineThick) {
    this._polylineShap.attr("stroke-width", g_markupLineWidth * wLineThick / 2);
    if (this._ballShap)
      this._ballShap.attr("stroke-width", g_markupLineWidth * wLineThick / 2);
  }

  if (sLineStyle != 0) {
    this._polylineShap.attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[sLineStyle]);
    if (this._ballShap)
      this._ballShap.attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[sLineStyle]);
  }

  this._polylineShap.attr("fill", "#00000000");
  if (this._ballShap != null) {
    var fillcolor = nRGBFillColor;
    this._ballShap.attr("fill", sFillType == 1 ? fillcolor : "#00000000");
    this._ballShapBottom.attr("fill", sFillType == 2 ? fillcolor : "#00000000");

  }
}

/**
 * 包围盒及黑顶绘制 
 */
MarkupBallMarker.prototype.addBoundBoxContents = function () {
  var _MarkupBaseSelf = this;
  var minX = d3.min(this.originData.pointList, function (d) { return d.x; }),
    minY = d3.min(this.originData.pointList, function (d) { return d.y; }),
    maxX = d3.max(this.originData.pointList, function (d) { return d.x; }),
    maxY = d3.max(this.originData.pointList, function (d) { return d.y; });

  var width = Math.abs(maxX - minX);
  var height = Math.abs(maxY - minY);
  var blockWidth = g_editDotWidth;
  // var strokeWidth = this.originData.selectedLineWidth / 2;
  var strokeWidth = 0;

  if (this.boundBoxShap == null)
    this.boundBoxShap = this.boundboxGroup.append("rect");

  this.boundBoxShap
    .attr("x", minX - blockWidth - strokeWidth)
    .attr("y", minY - blockWidth - strokeWidth)
    .attr("width", width + blockWidth * 2 + strokeWidth * 2)
    .attr("height", height + blockWidth * 2 + strokeWidth * 2)
    .attr("stroke-dasharray", LINE_STROKE_DASH_TYPE[2])
    .attr("stroke", "#00000033")
    .attr("fill", "#00000000")
    .attr("stroke-width", g_markupLineWidth * 2 / 2);

  this.boundBoxShap.on("mousedown", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseDown(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  this.boundBoxShap.on("mouseup", function () {
    var dataindex = d3.select(this).attr("dataIndex");
    _MarkupBaseSelf.onBoundBoxShapeMouseUp(dataindex);
    event.stopPropagation();//阻止事件冒泡
    event.preventDefault();  //阻止默认行为
  });

  for (var i = 0; i < this.originData.pointList.length; i++) {
    var tempDotInfo = this.originData.pointList[i];
    var dotInfoLeftBottom = {}; // data & shape

    var tempDotShape = null;
    // 初次创建
    if (_MarkupBaseSelf.boundboxDots.length >= i + 1 && _MarkupBaseSelf.boundboxDots[i] != null) {
      tempDotShape = _MarkupBaseSelf.boundboxDots[i].dotShap;
    }
    else {
      // 更改形状
      tempDotShape = this.boundboxGroup.append("rect");
      dotInfoLeftBottom.dotShap = tempDotShape;
      _MarkupBaseSelf.boundboxDots.push(dotInfoLeftBottom);

      tempDotShape.dataIndex = i;
      dotInfoLeftBottom.optType = i;

      // 点击黑点 
      tempDotShape.on("mousedown", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseDown(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });

      tempDotShape.on("mouseup", function () {
        var dataindex = d3.select(this).attr("dataIndex");
        _MarkupBaseSelf.onBoundBoxDotMouseUp(dataindex);
        event.stopPropagation();//阻止事件冒泡
        event.preventDefault();  //阻止默认行为
      });


      this.boundboxGroup.attr("visibility", "hidden");
    }

    // 修改形状
    tempDotShape
      .attr("x", tempDotInfo.x)
      .attr("y", tempDotInfo.y)
      .attr("width", g_editDotWidth)
      .attr("height", g_editDotWidth)
      .attr("stroke", g_editDotStroke)
      .attr("stroke-width", 1)
      .attr("dataIndex", i)
      .attr("fill", g_editDotFill);
  }
};

MarkupBallMarker.prototype.doAtAddEnd = function () {
  // if (this.typeId == 13) {
  //   this._ballShap = this.contentGroup.append("ellipse");
  // } else if (this.typeId == 14) {
  //   this._ballShap = this.contentGroup.append("rect");
  // } else if (this.typeId == 15 || this.typeId == 16) {
  //   this._ballShap = this.contentGroup.append("path");    // 标记 shape
  // }

  if (this.typeId == 13) {
    this._ballShap = this.contentGroup.insert("ellipse", "#ball_polyline");
    this._ballShapBottom = this.contentGroupBottom.append("ellipse");
  } else if (this.typeId == 14) {
    this._ballShap = this.contentGroup.insert("rect", "#ball_polyline");
    this._ballShapBottom = this.contentGroupBottom.append("rect");
  } else if (this.typeId == 15 || this.typeId == 16) {
    this._ballShap = this.contentGroup.insert("path", "#ball_polyline");    // 标记 shape
    this._ballShapBottom = this.contentGroupBottom.append("path");
  }
}

MarkupBallMarker.prototype.updateDrawShape = function (index, mouseosX, mouseosY) {
  if (index < this.originData.pointList.length) {
    this.originData.pointList[index].x = mouseosX;
    this.originData.pointList[index].y = mouseosY;
    this.addContents();
    this.addBoundBoxContents();
  }
};


/**
 * 根据传入的参数值创建markup
 * @param {*} shapeTypeId shape类型
 * @param {*} params 参数
 * @param {*} inPos 传入位置
 */
function addMarkUpByParams(shapeTypeId, params, inPos) {
  var markupData = {};
  var mouseosX = GetMousePositonOnSvgX();
  var mouseosY = GetMousePositonOnSvgY();

  markupData.pointList = [];
  markupData.pointList.push({ x: mouseosX, y: mouseosY });
  markupData.pointList.push({ x: mouseosX, y: mouseosY });

  markupData.selectedFont = params.selectedFont;
  markupData.selectedFontSize = params.selectedFontSize;

  markupData.selectedBold = params.selectedBold;
  markupData.selectedItalics = params.selectedItalics;
  markupData.selectedUnderline = params.selectedUnderline;

  markupData.selectedLineType = params.selectedLineType;
  markupData.selectedLineWidth = params.selectedLineWidth;

  markupData.selectedLineColor = params.selectedLineColor;
  markupData.selectedFillColor = params.selectedFillColor;

  markupData.selectedFillType = params.selectedFillType;

  markupData.text = "测试一下文字信息";

  var testShape = null;
  if (shapeTypeId == 1) {
    markupData.selectedFillType = 0;
    testShape = new MarkupLine(markupData, shapeTypeId);
  } else if (shapeTypeId == 2) {
    markupData.selectedFillType = 0;
    testShape = new MarkupLine(markupData, shapeTypeId);
  } else if (shapeTypeId == 3) {
    if (markupData.selectedFillType == 0)
      markupData.selectedFillType = 1;
    testShape = new MarkupLine(markupData, shapeTypeId);
  } else if (shapeTypeId == 4) {
    markupData.selectedFillType = 0;
    testShape = new MarkupRect(markupData, shapeTypeId);
  } else if (shapeTypeId == 12) {
    markupData.selectedFillType = 0;
    markupData.selectedFillColor = markupData.selectedLineColor;
    markupData.selectedFillType = 1;
    testShape = new MarkupRect(markupData, shapeTypeId);
  }
  else if (shapeTypeId == 5) {
    if (markupData.selectedFillType == 0)
      markupData.selectedFillType = 1;
    testShape = new MarkupRect(markupData, shapeTypeId);
  } else if (shapeTypeId == 6) {
    markupData.selectedFillType = 0;
    testShape = new MarkupEllipse(markupData, shapeTypeId);
  } else if (shapeTypeId == 7) {
    markupData.selectedFillType = 0;
    testShape = new MarkupArc(markupData, shapeTypeId);
  } else if (shapeTypeId == 8) {
    markupData.selectedFillType = 0;
    testShape = new MarkupHandDraw(markupData, shapeTypeId);
  } else if (shapeTypeId == 9) { // cloud
    markupData.selectedFillType = 0;
    testShape = new MarkupCloudDraw(markupData, shapeTypeId);
  } else if (shapeTypeId == 10) { // text
    markupData.selectedFillType = 0;
    testShape = new MarkupText(markupData, shapeTypeId);

    if (shapeTypeId == 10) { // text
      if (g_openTextInputFun)
        g_openTextInputFun("");
      // return;
    }
  }
  else if (shapeTypeId == 11) { // text
    testShape = new MarkupPolylineAndText(markupData, shapeTypeId);
  }
  else if (shapeTypeId >= 13 && shapeTypeId <= 16) { // text
    testShape = new MarkupBallMarker(markupData, shapeTypeId);
  }

  g_markupList.push(testShape);
  return testShape;
}

/**
 * 鼠标点击 增加一个点数据
 * @param {*} shapeTypeId 
 * @param {*} params 
 * @param {*} inPos 
 */
function addMarkUpPosition(shapeTypeId, params, inPos) {
  var tempTypeId = g_SelectedMarkup.typeId;
  var posList = g_SelectedMarkup.originData.pointList;
  var posListLen = posList.length;

  var _isBackToAdd = false;

  if (tempTypeId == 1 || shapeTypeId == 4 || shapeTypeId == 5
    || shapeTypeId == 6 || shapeTypeId == 9 || shapeTypeId == 10) {
    if (posListLen < 2)
      posList.push(inPos);
    else
      _isBackToAdd = true;
  } else if (shapeTypeId == 2 || shapeTypeId == 3 || shapeTypeId == 11
    || (shapeTypeId >= 13 && shapeTypeId <= 16)) {
    posList.push(inPos);

  } else if (shapeTypeId == 7) {
    if (posListLen < 3)
      posList.push(inPos);
  }
  else if (shapeTypeId == 8) {
    posList.push(inPos);
  }

  g_SelectedMarkup.addContents();
  g_SelectedMarkup.addBoundBoxContents();
  return _isBackToAdd;
}

function tryDeleteMarkup() {
  if (g_state == OPT_STATE.STATE_NORMAL) {
    if (g_SelectedMarkup != null && g_SelectedMarkup.isSelected) {

      for (var i = 0; i < g_markupList.length; i++) {
        var listItem = g_markupList[i];
        if (listItem == g_SelectedMarkup) {
          g_markupList.splice(i, 1);
          break;
        }
      }

      g_SelectedMarkup.rootGroup.remove();
      g_SelectedMarkup.contentGroupBottom.remove();

      g_SelectedMarkup = null;
    }

  }
}

function clearAllMarkups() {
  for (var i = 0; i < g_markupList.length; i++) {
    var listItem = g_markupList[i];
    listItem.rootGroup.remove();
    listItem.contentGroupBottom.remove();
    g_markupList.splice(i, 1);
    i--;
  }
}

function onInputDialogClose() {
  if (g_state == OPT_STATE.STATE_ADDING)
    changeGlobalState(3, g_createShapeTypeId);
}

/**
 * 点沿向量移动的一段距离后的点
 * @param {*} vectorIn 
 * @param {*} point 
 * @param {*} distance 
 */
var movePointByVector = (vectorIn, point, distance) => {
  var vectorMagnitude = Math.sqrt(Math.pow(vectorIn.x, 2) + Math.pow(vectorIn.y, 2))

  var unitVector = {};
  unitVector.x = vectorIn.x / vectorMagnitude;
  unitVector.y = vectorIn.y / vectorMagnitude;

  var re = { x: point.x + (unitVector.x * distance), y: point.y + (unitVector.y * distance) };

  return re;
}

function setUpdateMarkupBaseInfoCallback(fun) {
  g_updateMarkupBaseInfoFun = fun;
}

/**
 * 文件导入Markup数据
 * @param {*} path 
 */
function loadMarkupsFromFile(path) {
  var getValueAndFliterDot = function (parentTag, tagName) {
    var type = parentTag.getElementsByTagName(tagName)[0].textContent;
    var typeNew = type.replace(/"/g, "");
    return typeNew;
  };

  // 创建一个新的xhr对象
  let xhr = null;
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
  } else {
    // IE
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
  }
  xhr.open("GET", path, false);
  xhr.overrideMimeType("text/html;charset=utf-8");
  xhr.send(null);
  // console.log(xhr.responseText.replace(/\s*/g, ""));
  var xmlStr = xhr.responseText;
  var parser = new DOMParser();

  if(xmlStr == null) {
    return false;
  }

  clearAllMarkups();
  var xmlDoc = parser.parseFromString(xmlStr, "text/xml");

  // 提取baseinfo
  var lstField = xmlDoc.getElementsByTagName("lstField");
  var baseI = {};

  if (lstField && lstField.length > 0) {
    baseI.userName = getValueAndFliterDot(lstField[0], "UserName");
    baseI.departName = getValueAndFliterDot(lstField[0], "DepartName");
    baseI.companyName = getValueAndFliterDot(lstField[0], "CompanyName");
    baseI.address = getValueAndFliterDot(lstField[0], "Address");
    baseI.phoneNumber = getValueAndFliterDot(lstField[0], "PhoneNumber");
  }

  if (g_updateMarkupBaseInfoFun)
    g_updateMarkupBaseInfoFun(baseI);

  //提取数据
  var countrys = xmlDoc.getElementsByTagName("Entity");

  for (var i = 0; i < countrys.length; i++) {
    var markupData = transMarkupDataFromFile(countrys[i]);

    var testRect = null;
    if (markupData.fEntType == 1)
      testRect = new MarkupLine(markupData, markupData.fEntType);
    else if (markupData.fEntType == 2)
      testRect = new MarkupLine(markupData, markupData.fEntType);
    else if (markupData.fEntType == 3)
      testRect = new MarkupLine(markupData, markupData.fEntType);
    else if (markupData.fEntType == 4 || markupData.fEntType == 5 || markupData.fEntType == 12) {
      var point0 = markupData.pointList[0];
      var point1 = markupData.pointList[1];
      var maxx = Math.max(point0.x, point1.x);
      var minx = Math.min(point0.x, point1.x);
      var maxy = Math.max(point0.y, point1.y);
      var miny = Math.min(point0.y, point1.y);
      markupData.pointList[0].x = minx;
      markupData.pointList[0].y = miny;
      markupData.pointList[1].x = maxx;
      markupData.pointList[1].y = maxy;

      testRect = new MarkupRect(markupData, markupData.fEntType);
    }
    else if (markupData.fEntType == 6) {
      var point0 = markupData.pointList[0];
      var point1 = markupData.pointList[1];
      var maxx = Math.max(point0.x, point1.x);
      var minx = Math.min(point0.x, point1.x);
      var maxy = Math.max(point0.y, point1.y);
      var miny = Math.min(point0.y, point1.y);
      markupData.pointList[0].x = minx;
      markupData.pointList[0].y = miny;
      markupData.pointList[1].x = maxx;
      markupData.pointList[1].y = maxy;

      testRect = new MarkupEllipse(markupData, markupData.fEntType);
    }
    else if (markupData.fEntType == 7)
      testRect = new MarkupArc(markupData, markupData.fEntType);
    else if (markupData.fEntType == 8)
      testRect = new MarkupHandDraw(markupData, markupData.fEntType);
    else if (markupData.fEntType == 9)
      testRect = new MarkupCloudDraw(markupData, markupData.fEntType);
    else if (markupData.fEntType == 10) {
      var point0 = markupData.pointList[0];
      var point1 = markupData.pointList[1];
      var maxx = Math.max(point0.x, point1.x);
      var minx = Math.min(point0.x, point1.x);
      var maxy = Math.max(point0.y, point1.y);
      var miny = Math.min(point0.y, point1.y);
      markupData.pointList[0].x = minx;
      markupData.pointList[0].y = miny;
      markupData.pointList[1].x = maxx;
      markupData.pointList[1].y = maxy;
      testRect = new MarkupText(markupData, markupData.fEntType);
    }
    else if (markupData.fEntType == 11) { // text
      testRect = new MarkupPolylineAndText(markupData, markupData.fEntType);
    }
    else if (markupData.fEntType >= 13 && markupData.fEntType <= 16) { // text
      testRect = new MarkupBallMarker(markupData, markupData.fEntType);
    }

    if (testRect && testRect.doAtAddEnd != null) {
      testRect.doAtAddEnd();
      testRect.addContents();
      testRect.addBoundBoxContents();
    }

    g_markupList.push(testRect);
  }
  return true;
}

function transMarkupDataFromFile(e) {
  var markupData = {};
  var pointList = [];
  var points = e.getElementsByTagName("Point");

  for (var i = 0; i < points.length; i++) {
    var tempPoint = points[i];
    pointList.push({
      x: Number(tempPoint.getAttribute("x")),
      y: Number(tempPoint.getAttribute("y")),
    });
  }
  markupData.pointList = pointList;

  var getValueAndFliterDot = function (parentTag, tagName) {
    var type = parentTag.getElementsByTagName(tagName)[0].textContent;
    var typeNew = type.replace(/"/g, "");
    return typeNew;
  };

  var genValidColorStr = function (originColor) {
    var outputColor = '';
    var replaceed = originColor.replace("0x00", "");
    var bStr = replaceed.substring(0, 2);
    var gStr = replaceed.substring(2, 4);
    var rStr = replaceed.substring(4, 6);
    return '#' + rStr + gStr + bStr;
  };

  var nRGBLColor_temp = getValueAndFliterDot(e, "nRGBLColor");
  var nRGBLColor_temp_temp = genValidColorStr(nRGBLColor_temp);
  markupData.selectedLineColor = nRGBLColor_temp_temp;

  var nRGBFillColor_temp = getValueAndFliterDot(e, "nRGBFillColor");
  var nRGBFillColor_temp_temp = genValidColorStr(nRGBFillColor_temp);
  markupData.selectedFillColor = nRGBFillColor_temp_temp;

  markupData.selectedFillType = Number(getValueAndFliterDot(e, "sFillType"));
  markupData.selectedLineWidth = Number(getValueAndFliterDot(e, "wLineThick")) + 1;
  markupData.selectedLineType = Number(getValueAndFliterDot(e, "sLineStyle"));

  markupData.selectedFontSize = Number(getValueAndFliterDot(e, "sFontHeight"));
  markupData.text = getValueAndFliterDot(e, "strTextContents");
  markupData.fEntType = getValueAndFliterDot(e, "fEntType");
  return markupData;
}


function genMarkupsContent(baseInfo) {
  var createXMLDOM = function () {
    var xmlDOM;
    if (window.ActiveXObject) {
      xmlDOM = new ActiveXObject('Microsoft.XMLDOM');
    } else if (document.implementation
      && document.implementation.createDocument) {
      xmlDOM = document.implementation.createDocument('', '', null);
    } else {
      alert('您的浏览器不支持文档对象XMLDOM');
      return;
    }
    return xmlDOM;
  }

  var parserXMLToString = function (xmlDOM) {
    if (window.ActiveXObject) {
      return xmlDOM.xml;
    } else if (document.implementation
      && document.implementation.createDocument) {
      return new XMLSerializer().serializeToString(xmlDOM);
    }
  }

  var genColorStr = function (inColor) {
    var replaceed = inColor.replace("#", "");
    var rStr = replaceed.substring(0, 2);
    var gStr = replaceed.substring(2, 4);
    var bStr = replaceed.substring(4, 6);

    var out = "0x00" + bStr + gStr + rStr;
    return out;
  }



  var xmlDOM = createXMLDOM(); //参考：http://iceworldvip.blog.51cto.com/5438460/1341677
  if (xmlDOM == null) {
    return null;
  }

  var jpcMarkup = xmlDOM.createElement('jpcMarkup');
  xmlDOM.appendChild(jpcMarkup);

  var _baseInfo = xmlDOM.createElement('BaseInfo');
  jpcMarkup.appendChild(_baseInfo);

  var lstField = xmlDOM.createElement('lstField');
  _baseInfo.appendChild(lstField);

  if (baseInfo) {
    var userName = xmlDOM.createElement('UserName');
    lstField.appendChild(userName);
    userName.appendChild(xmlDOM.createTextNode(baseInfo.userName));

    var departName = xmlDOM.createElement('DepartName');
    lstField.appendChild(departName);
    departName.appendChild(xmlDOM.createTextNode(baseInfo.departName));

    var companyName = xmlDOM.createElement('CompanyName');
    lstField.appendChild(companyName);
    companyName.appendChild(xmlDOM.createTextNode(baseInfo.companyName));

    var address = xmlDOM.createElement('Address');
    lstField.appendChild(address);
    address.appendChild(xmlDOM.createTextNode(baseInfo.address));

    var phoneNumber = xmlDOM.createElement('PhoneNumber');
    lstField.appendChild(phoneNumber);
    phoneNumber.appendChild(xmlDOM.createTextNode(baseInfo.phoneNumber));
  }


  var entityData = xmlDOM.createElement('EntityData');
  jpcMarkup.appendChild(entityData);

  for (var i = 0; i < g_markupList.length; i++) {
    var tempMarkupListItem = g_markupList[i];
    var newEntity = xmlDOM.createElement('Entity');
    entityData.appendChild(newEntity);

    // <nID>"19"</nID>
    var entityNID = xmlDOM.createElement('nID');
    entityNID.appendChild(xmlDOM.createTextNode(tempMarkupListItem.id));
    newEntity.appendChild(entityNID);

    //<fEntType>"1"</fEntType>
    var entityfEntType = xmlDOM.createElement('fEntType');
    entityfEntType.appendChild(xmlDOM.createTextNode(tempMarkupListItem.typeId));
    newEntity.appendChild(entityfEntType);

    // <sLineStyle>"1"</sLineStyle>
    var entitysLineStyle = xmlDOM.createElement('sLineStyle');
    entitysLineStyle.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedLineType));
    newEntity.appendChild(entitysLineStyle);

    // <wLineThick>"8"</wLineThick>
    var entitywLineThick = xmlDOM.createElement('wLineThick');
    entitywLineThick.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedLineWidth - 1));
    newEntity.appendChild(entitywLineThick);

    // <sFillType>"1"</sFillType>
    var entitysFillType = xmlDOM.createElement('sFillType');
    entitysFillType.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedFillType));
    newEntity.appendChild(entitysFillType);

    // <nRGBLColor>"0x000000FF"</nRGBLColor>
    var entitynRGBLColor = xmlDOM.createElement('nRGBLColor');
    entitynRGBLColor.appendChild(xmlDOM.createTextNode(genColorStr(tempMarkupListItem.originData.selectedLineColor)));
    newEntity.appendChild(entitynRGBLColor);

    // <nRGBFillColor>"0x00FFFF00"</nRGBFillColor>
    var entitynRGBFillColor = xmlDOM.createElement('nRGBFillColor');
    entitynRGBFillColor.appendChild(xmlDOM.createTextNode(genColorStr(tempMarkupListItem.originData.selectedFillColor)));
    newEntity.appendChild(entitynRGBFillColor);

    for (var j = 0; j < tempMarkupListItem.originData.pointList.length; j++) {
      var temppoint = tempMarkupListItem.originData.pointList[j];
      var point = xmlDOM.createElement('Point');
      point.setAttribute('x', temppoint.x.toFixed(6));
      point.setAttribute('y', temppoint.y.toFixed(6));
      point.setAttribute('z', "0.000000");
      point.appendChild(xmlDOM.createTextNode(" "));
      newEntity.appendChild(point);
    }

    // <sFontHeight>"10"</sFontHeight>
    var entitysFontHeight = xmlDOM.createElement('sFontHeight');
    entitysFontHeight.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedFontSize));
    newEntity.appendChild(entitysFontHeight);

    // <sFontWidth>"5"</sFontWidth>
    var entitysFontWidth = xmlDOM.createElement('sFontWidth');
    var fontwidth = 0;
    var point1 = tempMarkupListItem.originData.pointList[0]; // 点1
    var point2 = tempMarkupListItem.originData.pointList[1]; // 点2
    if (tempMarkupListItem.originData.text && tempMarkupListItem.originData.text.length > 0) {
      var tempwidth = Math.abs(point1.x - point2.x)
      fontwidth = parseInt(tempwidth / tempMarkupListItem.originData.text.length * 0.5)
    }
    // entitysFontWidth.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedFontSize));
    entitysFontWidth.appendChild(xmlDOM.createTextNode(fontwidth));

    newEntity.appendChild(entitysFontWidth);

    // <sFontBold>"0"</sFontBold>
    var entitysFontBold = xmlDOM.createElement('sFontBold');
    entitysFontBold.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedBold ? "400" : "0"));
    newEntity.appendChild(entitysFontBold);

    // <bFontItaly>"0"</bFontItaly>
    var entitybFontItaly = xmlDOM.createElement('bFontItaly');
    entitybFontItaly.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedItalics ? "1" : "0"));
    newEntity.appendChild(entitybFontItaly);

    // <bFontUnderLine>"0"</bFontUnderLine>
    var entitybFontUnderLine = xmlDOM.createElement('bFontUnderLine');
    entitybFontUnderLine.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedUnderline ? "1" : "0"));
    newEntity.appendChild(entitybFontUnderLine);

    // <strFontName>"楷体"</strFontName>
    var entitystrFontName = xmlDOM.createElement('strFontName');
    entitystrFontName.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.selectedFont));
    newEntity.appendChild(entitystrFontName);

    // <strTextContents>"范德萨发生大"</strTextContents>
    var entitystrTextContents = xmlDOM.createElement('strTextContents');
    entitystrTextContents.appendChild(xmlDOM.createTextNode(tempMarkupListItem.originData.text));
    newEntity.appendChild(entitystrTextContents);
  }

  var xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + parserXMLToString(xmlDOM);
  // console.log(xmlStr);

  var re = formateXml(xmlStr)
  return re;
}


//格式化xml代码
function formateXml(xmlStr) {
  var text = xmlStr;
  //使用replace去空格
  text = '\n' + text.replace(/(<\w+)(\s.*?>)/g, function ($0, name, props) {
    return name + ' ' + props.replace(/\s+(\w+=)/g, " $1");
  }).replace(/>\s*?</g, ">\n<");
  //处理注释
  text = text.replace(/\n/g, '\r').replace(/<!--(.+?)-->/g, function ($0, text) {
    var ret = '<!--' + escape(text) + '-->';
    return ret;
  }).replace(/\r/g, '\n');
  //调整格式  以压栈方式递归调整缩进
  var rgx = /\n(<(([^\?]).+?)(?:\s|\s*?>|\s*?(\/)>)(?:.*?(?:(?:(\/)>)|(?:<(\/)\2>)))?)/mg;
  var nodeStack = [];
  var output = text.replace(rgx, function ($0, all, name, isBegin, isCloseFull1, isCloseFull2, isFull1, isFull2) {
    var isClosed = (isCloseFull1 == '/') || (isCloseFull2 == '/') || (isFull1 == '/') || (isFull2 == '/');
    var prefix = '';
    if (isBegin == '!') {//!开头
      prefix = setPrefix(nodeStack.length);
    } else {
      if (isBegin != '/') {///开头
        prefix = setPrefix(nodeStack.length);
        if (!isClosed) {//非关闭标签
          nodeStack.push(name);
        }
      } else {
        nodeStack.pop();//弹栈
        prefix = setPrefix(nodeStack.length);
      }
    }
    var ret = '\n' + prefix + all;
    return ret;
  });
  var prefixSpace = -1;
  var outputText = output.substring(1);
  //还原注释内容
  outputText = outputText.replace(/\n/g, '\r').replace(/(\s*)<!--(.+?)-->/g, function ($0, prefix, text) {
    if (prefix.charAt(0) == '\r')
      prefix = prefix.substring(1);
    text = unescape(text).replace(/\r/g, '\n');
    var ret = '\n' + prefix + '<!--' + text.replace(/^\s*/mg, prefix) + '-->';
    return ret;
  });
  outputText = outputText.replace(/\s+$/g, '').replace(/\r/g, '\r\n');
  return outputText;
}

//计算头函数 用来缩进
function setPrefix(prefixIndex) {
  var result = '';
  var span = '    ';//缩进长度
  var output = [];
  for (var i = 0; i < prefixIndex; ++i) {
    output.push(span);
  }
  result = output.join('');
  return result;
}

export {
  AddSvg as AddSvg,
  ResetSvgView as ResetSvgView,
  SetSvgMouseMode as SetSvgMouseMode,
  GetMousePositonOnSvgX as GetMousePositonOnSvgX,
  GetMousePositonOnSvgY as GetMousePositonOnSvgY,
  AddSimpleMarkup as AddSimpleMarkup,
  initMarkupLayer as initMarkupLayer,
  setGParams as setGParams,
  changeGlobalState as changeGlobalState,
  setSelectCallBack as setSelectCallBack,
  setLoadCallBack as setLoadCallBack,
  setOpenInputTextCallBack as setOpenInputTextCallBack,
  onInputDialogClose as onInputDialogClose,
  loadMarkupsFromFile as loadMarkupsFromFile,
  setUpdateMarkupBaseInfoCallback as setUpdateMarkupBaseInfoCallback,
  tryDeleteMarkup as tryDeleteMarkup,
  genMarkupsContent as genMarkupsContent,
  clearAllMarkups as clearAllMarkups,

  MarkupRect as MarkupRect,
  MarkupLine as MarkupLine,
  MarkupEllipse as MarkupEllipse,
  MarkupArc as MarkupArc,
  MarkupText as MarkupText,
  MarkupHandDraw as MarkupHandDraw,
  MarkupCloudDraw as MarkupCloudDraw
}